1 : /******************************************************************************
2 : * $Id: vrtsourcedrasterband.cpp 25109 2012-10-13 11:51:23Z rouault $
3 : *
4 : * Project: Virtual GDAL Datasets
5 : * Purpose: Implementation of VRTSourcedRasterBand
6 : * Author: Frank Warmerdam <warmerdam@pobox.com>
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2001, 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 :
34 : CPL_CVSID("$Id: vrtsourcedrasterband.cpp 25109 2012-10-13 11:51:23Z rouault $");
35 :
36 : /************************************************************************/
37 : /* ==================================================================== */
38 : /* VRTSourcedRasterBand */
39 : /* ==================================================================== */
40 : /************************************************************************/
41 :
42 : /************************************************************************/
43 : /* VRTSourcedRasterBand() */
44 : /************************************************************************/
45 :
46 473 : VRTSourcedRasterBand::VRTSourcedRasterBand( GDALDataset *poDS, int nBand )
47 :
48 : {
49 473 : Initialize( poDS->GetRasterXSize(), poDS->GetRasterYSize() );
50 :
51 473 : this->poDS = poDS;
52 473 : this->nBand = nBand;
53 473 : }
54 :
55 : /************************************************************************/
56 : /* VRTSourcedRasterBand() */
57 : /************************************************************************/
58 :
59 0 : VRTSourcedRasterBand::VRTSourcedRasterBand( GDALDataType eType,
60 0 : int nXSize, int nYSize )
61 :
62 : {
63 0 : Initialize( nXSize, nYSize );
64 :
65 0 : eDataType = eType;
66 0 : }
67 :
68 : /************************************************************************/
69 : /* VRTSourcedRasterBand() */
70 : /************************************************************************/
71 :
72 1911 : VRTSourcedRasterBand::VRTSourcedRasterBand( GDALDataset *poDS, int nBand,
73 : GDALDataType eType,
74 1911 : int nXSize, int nYSize )
75 :
76 : {
77 1911 : Initialize( nXSize, nYSize );
78 :
79 1911 : this->poDS = poDS;
80 1911 : this->nBand = nBand;
81 :
82 1911 : eDataType = eType;
83 1911 : }
84 :
85 : /************************************************************************/
86 : /* Initialize() */
87 : /************************************************************************/
88 :
89 2384 : void VRTSourcedRasterBand::Initialize( int nXSize, int nYSize )
90 :
91 : {
92 2384 : VRTRasterBand::Initialize( nXSize, nYSize );
93 :
94 2384 : nSources = 0;
95 2384 : papoSources = NULL;
96 2384 : bEqualAreas = FALSE;
97 2384 : bAntiRecursionFlag = FALSE;
98 2384 : }
99 :
100 : /************************************************************************/
101 : /* ~VRTSourcedRasterBand() */
102 : /************************************************************************/
103 :
104 2384 : VRTSourcedRasterBand::~VRTSourcedRasterBand()
105 :
106 : {
107 2384 : CloseDependentDatasets();
108 2384 : }
109 :
110 : /************************************************************************/
111 : /* IRasterIO() */
112 : /************************************************************************/
113 :
114 15903 : CPLErr VRTSourcedRasterBand::IRasterIO( GDALRWFlag eRWFlag,
115 : int nXOff, int nYOff, int nXSize, int nYSize,
116 : void * pData, int nBufXSize, int nBufYSize,
117 : GDALDataType eBufType,
118 : int nPixelSpace, int nLineSpace )
119 :
120 : {
121 : int iSource;
122 15903 : CPLErr eErr = CE_None;
123 :
124 15903 : if( eRWFlag == GF_Write )
125 : {
126 : CPLError( CE_Failure, CPLE_AppDefined,
127 0 : "Writing through VRTSourcedRasterBand is not supported." );
128 0 : return CE_Failure;
129 : }
130 :
131 : /* When using GDALProxyPoolDataset for sources, the recusion will not be */
132 : /* detected at VRT opening but when doing RasterIO. As the proxy pool will */
133 : /* return the already opened dataset, we can just test a member variable. */
134 15903 : if ( bAntiRecursionFlag )
135 : {
136 : CPLError( CE_Failure, CPLE_AppDefined,
137 : "VRTSourcedRasterBand::IRasterIO() called recursively on the same band. "
138 0 : "It looks like the VRT is referencing itself." );
139 0 : return CE_Failure;
140 : }
141 :
142 : /* ==================================================================== */
143 : /* Do we have overviews that would be appropriate to satisfy */
144 : /* this request? */
145 : /* ==================================================================== */
146 16779 : if( (nBufXSize < nXSize || nBufYSize < nYSize)
147 876 : && GetOverviewCount() > 0 )
148 : {
149 0 : if( OverviewRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
150 : pData, nBufXSize, nBufYSize,
151 : eBufType, nPixelSpace, nLineSpace ) == CE_None )
152 0 : return CE_None;
153 : }
154 :
155 : /* -------------------------------------------------------------------- */
156 : /* Initialize the buffer to some background value. Use the */
157 : /* nodata value if available. */
158 : /* -------------------------------------------------------------------- */
159 15903 : if ( nPixelSpace == GDALGetDataTypeSize(eBufType)/8 &&
160 : (!bNoDataValueSet || (!CPLIsNan(dfNoDataValue) && dfNoDataValue == 0)) )
161 : {
162 14272 : if (nLineSpace == nBufXSize * nPixelSpace)
163 : {
164 14258 : memset( pData, 0, (GIntBig)nBufYSize * nLineSpace );
165 : }
166 : else
167 : {
168 : int iLine;
169 1538 : for( iLine = 0; iLine < nBufYSize; iLine++ )
170 : {
171 1524 : memset( ((GByte*)pData) + (GIntBig)iLine * nLineSpace, 0, nBufXSize * nPixelSpace );
172 : }
173 : }
174 : }
175 1631 : else if ( !bEqualAreas || bNoDataValueSet )
176 : {
177 1631 : double dfWriteValue = 0.0;
178 : int iLine;
179 :
180 1631 : if( bNoDataValueSet )
181 1631 : dfWriteValue = dfNoDataValue;
182 :
183 5544 : for( iLine = 0; iLine < nBufYSize; iLine++ )
184 : {
185 : GDALCopyWords( &dfWriteValue, GDT_Float64, 0,
186 : ((GByte *)pData) + (GIntBig)nLineSpace * iLine,
187 3913 : eBufType, nPixelSpace, nBufXSize );
188 : }
189 : }
190 :
191 15903 : bAntiRecursionFlag = TRUE;
192 :
193 : /* -------------------------------------------------------------------- */
194 : /* Overlay each source in turn over top this. */
195 : /* -------------------------------------------------------------------- */
196 35307 : for( iSource = 0; eErr == CE_None && iSource < nSources; iSource++ )
197 : {
198 : eErr =
199 58212 : papoSources[iSource]->RasterIO( nXOff, nYOff, nXSize, nYSize,
200 : pData, nBufXSize, nBufYSize,
201 77616 : eBufType, nPixelSpace, nLineSpace);
202 : }
203 :
204 15903 : bAntiRecursionFlag = FALSE;
205 :
206 15903 : return eErr;
207 : }
208 :
209 : /************************************************************************/
210 : /* IReadBlock() */
211 : /************************************************************************/
212 :
213 53 : CPLErr VRTSourcedRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
214 : void * pImage )
215 :
216 : {
217 53 : int nPixelSize = GDALGetDataTypeSize(eDataType)/8;
218 : int nReadXSize, nReadYSize;
219 :
220 53 : if( (nBlockXOff+1) * nBlockXSize > GetXSize() )
221 12 : nReadXSize = GetXSize() - nBlockXOff * nBlockXSize;
222 : else
223 41 : nReadXSize = nBlockXSize;
224 :
225 53 : if( (nBlockYOff+1) * nBlockYSize > GetYSize() )
226 16 : nReadYSize = GetYSize() - nBlockYOff * nBlockYSize;
227 : else
228 37 : nReadYSize = nBlockYSize;
229 :
230 : return IRasterIO( GF_Read,
231 : nBlockXOff * nBlockXSize, nBlockYOff * nBlockYSize,
232 : nReadXSize, nReadYSize,
233 : pImage, nReadXSize, nReadYSize, eDataType,
234 53 : nPixelSize, nPixelSize * nBlockXSize );
235 : }
236 :
237 : /************************************************************************/
238 : /* GetMinimum() */
239 : /************************************************************************/
240 :
241 10 : double VRTSourcedRasterBand::GetMinimum( int *pbSuccess )
242 : {
243 10 : const char *pszValue = NULL;
244 :
245 10 : if( (pszValue = GetMetadataItem("STATISTICS_MINIMUM")) != NULL )
246 : {
247 1 : if( pbSuccess != NULL )
248 1 : *pbSuccess = TRUE;
249 :
250 1 : return CPLAtofM(pszValue);
251 : }
252 :
253 9 : if ( bAntiRecursionFlag )
254 : {
255 : CPLError( CE_Failure, CPLE_AppDefined,
256 : "VRTSourcedRasterBand::GetMinimum() called recursively on the same band. "
257 0 : "It looks like the VRT is referencing itself." );
258 0 : if( pbSuccess != NULL )
259 0 : *pbSuccess = FALSE;
260 0 : return 0.0;
261 : }
262 9 : bAntiRecursionFlag = TRUE;
263 :
264 9 : double dfMin = 0;
265 10 : for( int iSource = 0; iSource < nSources; iSource++ )
266 : {
267 9 : int bSuccess = FALSE;
268 9 : double dfSourceMin = papoSources[iSource]->GetMinimum(GetXSize(), GetYSize(), &bSuccess);
269 9 : if (!bSuccess)
270 : {
271 8 : dfMin = GDALRasterBand::GetMinimum(pbSuccess);
272 8 : bAntiRecursionFlag = FALSE;
273 8 : return dfMin;
274 : }
275 :
276 1 : if (iSource == 0 || dfSourceMin < dfMin)
277 1 : dfMin = dfSourceMin;
278 : }
279 :
280 1 : bAntiRecursionFlag = FALSE;
281 :
282 1 : if( pbSuccess != NULL )
283 1 : *pbSuccess = TRUE;
284 :
285 1 : return dfMin;
286 : }
287 :
288 : /************************************************************************/
289 : /* GetMaximum() */
290 : /************************************************************************/
291 :
292 10 : double VRTSourcedRasterBand::GetMaximum(int *pbSuccess )
293 : {
294 10 : const char *pszValue = NULL;
295 :
296 10 : if( (pszValue = GetMetadataItem("STATISTICS_MAXIMUM")) != NULL )
297 : {
298 1 : if( pbSuccess != NULL )
299 1 : *pbSuccess = TRUE;
300 :
301 1 : return CPLAtofM(pszValue);
302 : }
303 :
304 9 : if ( bAntiRecursionFlag )
305 : {
306 : CPLError( CE_Failure, CPLE_AppDefined,
307 : "VRTSourcedRasterBand::GetMaximum() called recursively on the same band. "
308 0 : "It looks like the VRT is referencing itself." );
309 0 : if( pbSuccess != NULL )
310 0 : *pbSuccess = FALSE;
311 0 : return 0.0;
312 : }
313 9 : bAntiRecursionFlag = TRUE;
314 :
315 9 : double dfMax = 0;
316 10 : for( int iSource = 0; iSource < nSources; iSource++ )
317 : {
318 9 : int bSuccess = FALSE;
319 9 : double dfSourceMax = papoSources[iSource]->GetMaximum(GetXSize(), GetYSize(), &bSuccess);
320 9 : if (!bSuccess)
321 : {
322 8 : dfMax = GDALRasterBand::GetMaximum(pbSuccess);
323 8 : bAntiRecursionFlag = FALSE;
324 8 : return dfMax;
325 : }
326 :
327 1 : if (iSource == 0 || dfSourceMax > dfMax)
328 1 : dfMax = dfSourceMax;
329 : }
330 :
331 1 : bAntiRecursionFlag = FALSE;
332 :
333 1 : if( pbSuccess != NULL )
334 1 : *pbSuccess = TRUE;
335 :
336 1 : return dfMax;
337 : }
338 :
339 : /************************************************************************/
340 : /* ComputeRasterMinMax() */
341 : /************************************************************************/
342 :
343 1 : CPLErr VRTSourcedRasterBand::ComputeRasterMinMax( int bApproxOK, double* adfMinMax )
344 : {
345 1 : double dfMin = 0.0;
346 1 : double dfMax = 0.0;
347 :
348 : /* -------------------------------------------------------------------- */
349 : /* Does the driver already know the min/max? */
350 : /* -------------------------------------------------------------------- */
351 1 : if( bApproxOK )
352 : {
353 : int bSuccessMin, bSuccessMax;
354 :
355 0 : dfMin = GetMinimum( &bSuccessMin );
356 0 : dfMax = GetMaximum( &bSuccessMax );
357 :
358 0 : if( bSuccessMin && bSuccessMax )
359 : {
360 0 : adfMinMax[0] = dfMin;
361 0 : adfMinMax[1] = dfMax;
362 0 : return CE_None;
363 : }
364 : }
365 :
366 : /* -------------------------------------------------------------------- */
367 : /* If we have overview bands, use them for min/max. */
368 : /* -------------------------------------------------------------------- */
369 1 : if ( bApproxOK && GetOverviewCount() > 0 && !HasArbitraryOverviews() )
370 : {
371 : GDALRasterBand *poBand;
372 :
373 0 : poBand = GetRasterSampleOverview( GDALSTAT_APPROX_NUMSAMPLES );
374 :
375 0 : if ( poBand != this )
376 0 : return poBand->ComputeRasterMinMax( FALSE, adfMinMax );
377 : }
378 :
379 : /* -------------------------------------------------------------------- */
380 : /* Try with source bands. */
381 : /* -------------------------------------------------------------------- */
382 1 : if ( bAntiRecursionFlag )
383 : {
384 : CPLError( CE_Failure, CPLE_AppDefined,
385 : "VRTSourcedRasterBand::ComputeRasterMinMax() called recursively on the same band. "
386 0 : "It looks like the VRT is referencing itself." );
387 0 : return CE_Failure;
388 : }
389 1 : bAntiRecursionFlag = TRUE;
390 :
391 1 : adfMinMax[0] = 0.0;
392 1 : adfMinMax[1] = 0.0;
393 2 : for( int iSource = 0; iSource < nSources; iSource++ )
394 : {
395 : double adfSourceMinMax[2];
396 1 : CPLErr eErr = papoSources[iSource]->ComputeRasterMinMax(GetXSize(), GetYSize(), bApproxOK, adfSourceMinMax);
397 1 : if (eErr != CE_None)
398 : {
399 0 : eErr = GDALRasterBand::ComputeRasterMinMax(bApproxOK, adfMinMax);
400 0 : bAntiRecursionFlag = FALSE;
401 0 : return eErr;
402 : }
403 :
404 1 : if (iSource == 0 || adfSourceMinMax[0] < adfMinMax[0])
405 1 : adfMinMax[0] = adfSourceMinMax[0];
406 1 : if (iSource == 0 || adfSourceMinMax[1] > adfMinMax[1])
407 1 : adfMinMax[1] = adfSourceMinMax[1];
408 : }
409 :
410 1 : bAntiRecursionFlag = FALSE;
411 :
412 1 : return CE_None;
413 : }
414 :
415 : /************************************************************************/
416 : /* ComputeStatistics() */
417 : /************************************************************************/
418 :
419 : CPLErr
420 2 : VRTSourcedRasterBand::ComputeStatistics( int bApproxOK,
421 : double *pdfMin, double *pdfMax,
422 : double *pdfMean, double *pdfStdDev,
423 : GDALProgressFunc pfnProgress,
424 : void *pProgressData )
425 :
426 : {
427 2 : if( nSources != 1 )
428 : return GDALRasterBand::ComputeStatistics( bApproxOK,
429 : pdfMin, pdfMax,
430 : pdfMean, pdfStdDev,
431 0 : pfnProgress, pProgressData );
432 :
433 2 : if( pfnProgress == NULL )
434 1 : pfnProgress = GDALDummyProgress;
435 :
436 : /* -------------------------------------------------------------------- */
437 : /* If we have overview bands, use them for statistics. */
438 : /* -------------------------------------------------------------------- */
439 2 : if( bApproxOK && GetOverviewCount() > 0 && !HasArbitraryOverviews() )
440 : {
441 : GDALRasterBand *poBand;
442 :
443 0 : poBand = GetRasterSampleOverview( GDALSTAT_APPROX_NUMSAMPLES );
444 :
445 0 : if( poBand != this )
446 : return poBand->ComputeStatistics( FALSE,
447 : pdfMin, pdfMax,
448 : pdfMean, pdfStdDev,
449 0 : pfnProgress, pProgressData );
450 : }
451 :
452 : /* -------------------------------------------------------------------- */
453 : /* Try with source bands. */
454 : /* -------------------------------------------------------------------- */
455 2 : if ( bAntiRecursionFlag )
456 : {
457 : CPLError( CE_Failure, CPLE_AppDefined,
458 : "VRTSourcedRasterBand::ComputeStatistics() called recursively on the same band. "
459 0 : "It looks like the VRT is referencing itself." );
460 0 : return CE_Failure;
461 : }
462 2 : bAntiRecursionFlag = TRUE;
463 :
464 2 : double dfMin = 0.0, dfMax = 0.0, dfMean = 0.0, dfStdDev = 0.0;
465 :
466 6 : CPLErr eErr = papoSources[0]->ComputeStatistics(GetXSize(), GetYSize(), bApproxOK,
467 : &dfMin, &dfMax,
468 : &dfMean, &dfStdDev,
469 8 : pfnProgress, pProgressData);
470 2 : if (eErr != CE_None)
471 : {
472 : eErr = GDALRasterBand::ComputeStatistics(bApproxOK,
473 : pdfMin, pdfMax,
474 : pdfMean, pdfStdDev,
475 0 : pfnProgress, pProgressData);
476 0 : bAntiRecursionFlag = FALSE;
477 0 : return eErr;
478 : }
479 :
480 2 : bAntiRecursionFlag = FALSE;
481 :
482 2 : SetStatistics( dfMin, dfMax, dfMean, dfStdDev );
483 :
484 : /* -------------------------------------------------------------------- */
485 : /* Record results. */
486 : /* -------------------------------------------------------------------- */
487 2 : if( pdfMin != NULL )
488 2 : *pdfMin = dfMin;
489 2 : if( pdfMax != NULL )
490 2 : *pdfMax = dfMax;
491 :
492 2 : if( pdfMean != NULL )
493 2 : *pdfMean = dfMean;
494 :
495 2 : if( pdfStdDev != NULL )
496 2 : *pdfStdDev = dfStdDev;
497 :
498 2 : return CE_None;
499 : }
500 :
501 : /************************************************************************/
502 : /* GetHistogram() */
503 : /************************************************************************/
504 :
505 1 : CPLErr VRTSourcedRasterBand::GetHistogram( double dfMin, double dfMax,
506 : int nBuckets, int *panHistogram,
507 : int bIncludeOutOfRange, int bApproxOK,
508 : GDALProgressFunc pfnProgress,
509 : void *pProgressData )
510 :
511 : {
512 1 : if( nSources != 1 )
513 : return GDALRasterBand::GetHistogram( dfMin, dfMax,
514 : nBuckets, panHistogram,
515 : bIncludeOutOfRange, bApproxOK,
516 0 : pfnProgress, pProgressData );
517 :
518 1 : if( pfnProgress == NULL )
519 1 : pfnProgress = GDALDummyProgress;
520 :
521 : /* -------------------------------------------------------------------- */
522 : /* If we have overviews, use them for the histogram. */
523 : /* -------------------------------------------------------------------- */
524 1 : if( bApproxOK && GetOverviewCount() > 0 && !HasArbitraryOverviews() )
525 : {
526 : // FIXME: should we use the most reduced overview here or use some
527 : // minimum number of samples like GDALRasterBand::ComputeStatistics()
528 : // does?
529 0 : GDALRasterBand *poBestOverview = GetRasterSampleOverview( 0 );
530 :
531 0 : if( poBestOverview != this )
532 : {
533 : return poBestOverview->GetHistogram( dfMin, dfMax, nBuckets,
534 : panHistogram,
535 : bIncludeOutOfRange, bApproxOK,
536 0 : pfnProgress, pProgressData );
537 : }
538 : }
539 :
540 : /* -------------------------------------------------------------------- */
541 : /* Try with source bands. */
542 : /* -------------------------------------------------------------------- */
543 1 : if ( bAntiRecursionFlag )
544 : {
545 : CPLError( CE_Failure, CPLE_AppDefined,
546 : "VRTSourcedRasterBand::GetHistogram() called recursively on the same band. "
547 0 : "It looks like the VRT is referencing itself." );
548 0 : return CE_Failure;
549 : }
550 1 : bAntiRecursionFlag = TRUE;
551 :
552 3 : CPLErr eErr = papoSources[0]->GetHistogram(GetXSize(), GetYSize(), dfMin, dfMax, nBuckets,
553 : panHistogram,
554 : bIncludeOutOfRange, bApproxOK,
555 4 : pfnProgress, pProgressData);
556 1 : if (eErr != CE_None)
557 : {
558 : eErr = GDALRasterBand::GetHistogram( dfMin, dfMax,
559 : nBuckets, panHistogram,
560 : bIncludeOutOfRange, bApproxOK,
561 0 : pfnProgress, pProgressData );
562 0 : bAntiRecursionFlag = FALSE;
563 0 : return eErr;
564 : }
565 :
566 1 : bAntiRecursionFlag = FALSE;
567 :
568 1 : return CE_None;
569 : }
570 :
571 : /************************************************************************/
572 : /* AddSource() */
573 : /************************************************************************/
574 :
575 5465 : CPLErr VRTSourcedRasterBand::AddSource( VRTSource *poNewSource )
576 :
577 : {
578 5465 : nSources++;
579 :
580 : papoSources = (VRTSource **)
581 5465 : CPLRealloc(papoSources, sizeof(void*) * nSources);
582 5465 : papoSources[nSources-1] = poNewSource;
583 :
584 5465 : ((VRTDataset *)poDS)->SetNeedsFlush();
585 :
586 5465 : return CE_None;
587 : }
588 :
589 : /************************************************************************/
590 : /* VRTAddSource() */
591 : /************************************************************************/
592 :
593 : /**
594 : * @see VRTSourcedRasterBand::AddSource().
595 : */
596 :
597 0 : CPLErr CPL_STDCALL VRTAddSource( VRTSourcedRasterBandH hVRTBand,
598 : VRTSourceH hNewSource )
599 : {
600 0 : VALIDATE_POINTER1( hVRTBand, "VRTAddSource", CE_Failure );
601 :
602 : return ((VRTSourcedRasterBand *) hVRTBand)->
603 0 : AddSource( (VRTSource *)hNewSource );
604 : }
605 :
606 : /************************************************************************/
607 : /* XMLInit() */
608 : /************************************************************************/
609 :
610 469 : CPLErr VRTSourcedRasterBand::XMLInit( CPLXMLNode * psTree,
611 : const char *pszVRTPath )
612 :
613 : {
614 : CPLErr eErr;
615 :
616 469 : eErr = VRTRasterBand::XMLInit( psTree, pszVRTPath );
617 469 : if( eErr != CE_None )
618 0 : return eErr;
619 :
620 : /* -------------------------------------------------------------------- */
621 : /* Validate a bit. */
622 : /* -------------------------------------------------------------------- */
623 469 : if( psTree == NULL || psTree->eType != CXT_Element
624 : || (!EQUAL(psTree->pszValue,"VRTSourcedRasterBand")
625 : && !EQUAL(psTree->pszValue,"VRTRasterBand")
626 : && !EQUAL(psTree->pszValue,"VRTDerivedRasterBand")) )
627 : {
628 : CPLError( CE_Failure, CPLE_AppDefined,
629 0 : "Invalid node passed to VRTSourcedRasterBand::XMLInit()." );
630 0 : return CE_Failure;
631 : }
632 :
633 : /* -------------------------------------------------------------------- */
634 : /* Process sources. */
635 : /* -------------------------------------------------------------------- */
636 : CPLXMLNode *psChild;
637 469 : VRTDriver *poDriver = (VRTDriver *) GDALGetDriverByName( "VRT" );
638 :
639 2237 : for( psChild = psTree->psChild;
640 : psChild != NULL && poDriver != NULL;
641 : psChild = psChild->psNext)
642 : {
643 : VRTSource *poSource;
644 :
645 1869 : if( psChild->eType != CXT_Element )
646 930 : continue;
647 :
648 939 : CPLErrorReset();
649 939 : poSource = poDriver->ParseSource( psChild, pszVRTPath );
650 939 : if( poSource != NULL )
651 354 : AddSource( poSource );
652 585 : else if( CPLGetLastErrorType() != CE_None )
653 101 : return CE_Failure;
654 : }
655 :
656 : /* -------------------------------------------------------------------- */
657 : /* Done. */
658 : /* -------------------------------------------------------------------- */
659 368 : if( nSources == 0 )
660 : CPLDebug( "VRT", "No valid sources found for band in VRT file:\n%s",
661 55 : pszVRTPath );
662 :
663 368 : return CE_None;
664 : }
665 :
666 : /************************************************************************/
667 : /* SerializeToXML() */
668 : /************************************************************************/
669 :
670 225 : CPLXMLNode *VRTSourcedRasterBand::SerializeToXML( const char *pszVRTPath )
671 :
672 : {
673 : CPLXMLNode *psTree;
674 :
675 225 : psTree = VRTRasterBand::SerializeToXML( pszVRTPath );
676 :
677 : /* -------------------------------------------------------------------- */
678 : /* Process Sources. */
679 : /* -------------------------------------------------------------------- */
680 420 : for( int iSource = 0; iSource < nSources; iSource++ )
681 : {
682 : CPLXMLNode *psXMLSrc;
683 :
684 195 : psXMLSrc = papoSources[iSource]->SerializeToXML( pszVRTPath );
685 :
686 195 : if( psXMLSrc != NULL )
687 195 : CPLAddXMLChild( psTree, psXMLSrc );
688 : }
689 :
690 225 : return psTree;
691 : }
692 :
693 : /************************************************************************/
694 : /* AddSimpleSource() */
695 : /************************************************************************/
696 :
697 5077 : CPLErr VRTSourcedRasterBand::AddSimpleSource( GDALRasterBand *poSrcBand,
698 : int nSrcXOff, int nSrcYOff,
699 : int nSrcXSize, int nSrcYSize,
700 : int nDstXOff, int nDstYOff,
701 : int nDstXSize, int nDstYSize,
702 : const char *pszResampling,
703 : double dfNoDataValue )
704 :
705 : {
706 : /* -------------------------------------------------------------------- */
707 : /* Default source and dest rectangles. */
708 : /* -------------------------------------------------------------------- */
709 5077 : if( nSrcYSize == -1 )
710 : {
711 111 : nSrcXOff = 0;
712 111 : nSrcYOff = 0;
713 111 : nSrcXSize = poSrcBand->GetXSize();
714 111 : nSrcYSize = poSrcBand->GetYSize();
715 : }
716 :
717 5077 : if( nDstYSize == -1 )
718 : {
719 111 : nDstXOff = 0;
720 111 : nDstYOff = 0;
721 111 : nDstXSize = nRasterXSize;
722 111 : nDstYSize = nRasterYSize;
723 : }
724 :
725 : /* -------------------------------------------------------------------- */
726 : /* Create source. */
727 : /* -------------------------------------------------------------------- */
728 : VRTSimpleSource *poSimpleSource;
729 :
730 5077 : if( pszResampling != NULL && EQUALN(pszResampling,"aver",4) )
731 0 : poSimpleSource = new VRTAveragedSource();
732 : else
733 : {
734 5077 : poSimpleSource = new VRTSimpleSource();
735 5077 : if( dfNoDataValue != VRT_NODATA_UNSET )
736 : CPLError(
737 : CE_Warning, CPLE_AppDefined,
738 : "NODATA setting not currently supported for nearest\n"
739 0 : "neighbour sampled simple sources on Virtual Datasources." );
740 : }
741 :
742 5077 : poSimpleSource->SetSrcBand( poSrcBand );
743 5077 : poSimpleSource->SetSrcWindow( nSrcXOff, nSrcYOff, nSrcXSize, nSrcYSize );
744 5077 : poSimpleSource->SetDstWindow( nDstXOff, nDstYOff, nDstXSize, nDstYSize );
745 :
746 5077 : if( dfNoDataValue != VRT_NODATA_UNSET )
747 0 : poSimpleSource->SetNoDataValue( dfNoDataValue );
748 :
749 : /* -------------------------------------------------------------------- */
750 : /* Default source and dest rectangles. */
751 : /* -------------------------------------------------------------------- */
752 5077 : if ( nSrcXOff == nDstXOff && nSrcYOff == nDstYOff &&
753 : nSrcXSize == nDstXSize && nSrcYSize == nRasterYSize )
754 203 : bEqualAreas = TRUE;
755 :
756 : /* -------------------------------------------------------------------- */
757 : /* If we can get the associated GDALDataset, add a reference to it.*/
758 : /* -------------------------------------------------------------------- */
759 5077 : if( poSrcBand->GetDataset() != NULL )
760 5077 : poSrcBand->GetDataset()->Reference();
761 :
762 : /* -------------------------------------------------------------------- */
763 : /* add to list. */
764 : /* -------------------------------------------------------------------- */
765 5077 : return AddSource( poSimpleSource );
766 : }
767 :
768 : /************************************************************************/
769 : /* AddMaskBandSource() */
770 : /************************************************************************/
771 :
772 : /* poSrcBand is not the mask band, but the band from which the mask band is taken */
773 5 : CPLErr VRTSourcedRasterBand::AddMaskBandSource( GDALRasterBand *poSrcBand,
774 : int nSrcXOff, int nSrcYOff,
775 : int nSrcXSize, int nSrcYSize,
776 : int nDstXOff, int nDstYOff,
777 : int nDstXSize, int nDstYSize )
778 : {
779 : /* -------------------------------------------------------------------- */
780 : /* Default source and dest rectangles. */
781 : /* -------------------------------------------------------------------- */
782 5 : if( nSrcYSize == -1 )
783 : {
784 2 : nSrcXOff = 0;
785 2 : nSrcYOff = 0;
786 2 : nSrcXSize = poSrcBand->GetXSize();
787 2 : nSrcYSize = poSrcBand->GetYSize();
788 : }
789 :
790 5 : if( nDstYSize == -1 )
791 : {
792 2 : nDstXOff = 0;
793 2 : nDstYOff = 0;
794 2 : nDstXSize = nRasterXSize;
795 2 : nDstYSize = nRasterYSize;
796 : }
797 :
798 : /* -------------------------------------------------------------------- */
799 : /* Create source. */
800 : /* -------------------------------------------------------------------- */
801 5 : VRTSimpleSource* poSimpleSource = new VRTSimpleSource();
802 5 : poSimpleSource->SetSrcMaskBand( poSrcBand );
803 5 : poSimpleSource->SetSrcWindow( 0, 0, poSrcBand->GetXSize(), poSrcBand->GetYSize() );
804 5 : poSimpleSource->SetDstWindow( 0, 0, nRasterXSize, nRasterYSize );
805 :
806 : /* -------------------------------------------------------------------- */
807 : /* Default source and dest rectangles. */
808 : /* -------------------------------------------------------------------- */
809 10 : if ( nSrcXOff == nDstXOff && nSrcYOff == nDstYOff &&
810 : nSrcXSize == nDstXSize && nSrcYSize == nRasterYSize )
811 5 : bEqualAreas = TRUE;
812 :
813 : /* -------------------------------------------------------------------- */
814 : /* If we can get the associated GDALDataset, add a reference to it.*/
815 : /* -------------------------------------------------------------------- */
816 5 : if( poSrcBand->GetDataset() != NULL )
817 5 : poSrcBand->GetDataset()->Reference();
818 :
819 : /* -------------------------------------------------------------------- */
820 : /* add to list. */
821 : /* -------------------------------------------------------------------- */
822 5 : return AddSource( poSimpleSource );
823 : }
824 :
825 : /************************************************************************/
826 : /* VRTAddSimpleSource() */
827 : /************************************************************************/
828 :
829 : /**
830 : * @see VRTSourcedRasterBand::AddSimpleSource().
831 : */
832 :
833 4841 : CPLErr CPL_STDCALL VRTAddSimpleSource( VRTSourcedRasterBandH hVRTBand,
834 : GDALRasterBandH hSrcBand,
835 : int nSrcXOff, int nSrcYOff,
836 : int nSrcXSize, int nSrcYSize,
837 : int nDstXOff, int nDstYOff,
838 : int nDstXSize, int nDstYSize,
839 : const char *pszResampling,
840 : double dfNoDataValue )
841 : {
842 4841 : VALIDATE_POINTER1( hVRTBand, "VRTAddSimpleSource", CE_Failure );
843 :
844 : return ((VRTSourcedRasterBand *) hVRTBand)->AddSimpleSource(
845 : (GDALRasterBand *)hSrcBand,
846 : nSrcXOff, nSrcYOff,
847 : nSrcXSize, nSrcYSize,
848 : nDstXOff, nDstYOff,
849 : nDstXSize, nDstYSize,
850 4841 : pszResampling, dfNoDataValue );
851 : }
852 :
853 : /************************************************************************/
854 : /* AddComplexSource() */
855 : /************************************************************************/
856 :
857 24 : CPLErr VRTSourcedRasterBand::AddComplexSource( GDALRasterBand *poSrcBand,
858 : int nSrcXOff, int nSrcYOff,
859 : int nSrcXSize, int nSrcYSize,
860 : int nDstXOff, int nDstYOff,
861 : int nDstXSize, int nDstYSize,
862 : double dfScaleOff,
863 : double dfScaleRatio,
864 : double dfNoDataValue,
865 : int nColorTableComponent)
866 :
867 : {
868 : /* -------------------------------------------------------------------- */
869 : /* Default source and dest rectangles. */
870 : /* -------------------------------------------------------------------- */
871 24 : if( nSrcYSize == -1 )
872 : {
873 0 : nSrcXOff = 0;
874 0 : nSrcYOff = 0;
875 0 : nSrcXSize = poSrcBand->GetXSize();
876 0 : nSrcYSize = poSrcBand->GetYSize();
877 : }
878 :
879 24 : if( nDstYSize == -1 )
880 : {
881 0 : nDstXOff = 0;
882 0 : nDstYOff = 0;
883 0 : nDstXSize = nRasterXSize;
884 0 : nDstYSize = nRasterYSize;
885 : }
886 :
887 : /* -------------------------------------------------------------------- */
888 : /* Create source. */
889 : /* -------------------------------------------------------------------- */
890 : VRTComplexSource *poSource;
891 :
892 24 : poSource = new VRTComplexSource();
893 :
894 24 : poSource->SetSrcBand( poSrcBand );
895 24 : poSource->SetSrcWindow( nSrcXOff, nSrcYOff, nSrcXSize, nSrcYSize );
896 24 : poSource->SetDstWindow( nDstXOff, nDstYOff, nDstXSize, nDstYSize );
897 :
898 : /* -------------------------------------------------------------------- */
899 : /* Set complex parameters. */
900 : /* -------------------------------------------------------------------- */
901 24 : if( dfNoDataValue != VRT_NODATA_UNSET )
902 8 : poSource->SetNoDataValue( dfNoDataValue );
903 :
904 24 : if( dfScaleOff != 0.0 || dfScaleRatio != 1.0 )
905 : {
906 1 : poSource->bDoScaling = TRUE;
907 1 : poSource->dfScaleOff = dfScaleOff;
908 1 : poSource->dfScaleRatio = dfScaleRatio;
909 :
910 : }
911 :
912 24 : poSource->nColorTableComponent = nColorTableComponent;
913 :
914 : /* -------------------------------------------------------------------- */
915 : /* If we can get the associated GDALDataset, add a reference to it.*/
916 : /* -------------------------------------------------------------------- */
917 24 : if( poSrcBand->GetDataset() != NULL )
918 24 : poSrcBand->GetDataset()->Reference();
919 :
920 : /* -------------------------------------------------------------------- */
921 : /* add to list. */
922 : /* -------------------------------------------------------------------- */
923 24 : return AddSource( poSource );
924 : }
925 :
926 : /************************************************************************/
927 : /* VRTAddComplexSource() */
928 : /************************************************************************/
929 :
930 : /**
931 : * @see VRTSourcedRasterBand::AddComplexSource().
932 : */
933 :
934 8 : CPLErr CPL_STDCALL VRTAddComplexSource( VRTSourcedRasterBandH hVRTBand,
935 : GDALRasterBandH hSrcBand,
936 : int nSrcXOff, int nSrcYOff,
937 : int nSrcXSize, int nSrcYSize,
938 : int nDstXOff, int nDstYOff,
939 : int nDstXSize, int nDstYSize,
940 : double dfScaleOff,
941 : double dfScaleRatio,
942 : double dfNoDataValue )
943 : {
944 8 : VALIDATE_POINTER1( hVRTBand, "VRTAddComplexSource", CE_Failure );
945 :
946 : return ((VRTSourcedRasterBand *) hVRTBand)->AddComplexSource(
947 : (GDALRasterBand *)hSrcBand,
948 : nSrcXOff, nSrcYOff,
949 : nSrcXSize, nSrcYSize,
950 : nDstXOff, nDstYOff,
951 : nDstXSize, nDstYSize,
952 : dfScaleOff, dfScaleRatio,
953 8 : dfNoDataValue );
954 : }
955 :
956 : /************************************************************************/
957 : /* AddFuncSource() */
958 : /************************************************************************/
959 :
960 0 : CPLErr VRTSourcedRasterBand::AddFuncSource( VRTImageReadFunc pfnReadFunc,
961 : void *pCBData, double dfNoDataValue )
962 :
963 : {
964 : /* -------------------------------------------------------------------- */
965 : /* Create source. */
966 : /* -------------------------------------------------------------------- */
967 0 : VRTFuncSource *poFuncSource = new VRTFuncSource;
968 :
969 0 : poFuncSource->fNoDataValue = (float) dfNoDataValue;
970 0 : poFuncSource->pfnReadFunc = pfnReadFunc;
971 0 : poFuncSource->pCBData = pCBData;
972 0 : poFuncSource->eType = GetRasterDataType();
973 :
974 : /* -------------------------------------------------------------------- */
975 : /* add to list. */
976 : /* -------------------------------------------------------------------- */
977 0 : return AddSource( poFuncSource );
978 : }
979 :
980 : /************************************************************************/
981 : /* VRTAddFuncSource() */
982 : /************************************************************************/
983 :
984 : /**
985 : * @see VRTSourcedRasterBand::AddFuncSource().
986 : */
987 :
988 0 : CPLErr CPL_STDCALL VRTAddFuncSource( VRTSourcedRasterBandH hVRTBand,
989 : VRTImageReadFunc pfnReadFunc,
990 : void *pCBData, double dfNoDataValue )
991 : {
992 0 : VALIDATE_POINTER1( hVRTBand, "VRTAddFuncSource", CE_Failure );
993 :
994 : return ((VRTSourcedRasterBand *) hVRTBand)->
995 0 : AddFuncSource( pfnReadFunc, pCBData, dfNoDataValue );
996 : }
997 :
998 :
999 : /************************************************************************/
1000 : /* GetMetadataItem() */
1001 : /************************************************************************/
1002 :
1003 4509 : const char *VRTSourcedRasterBand::GetMetadataItem( const char * pszName,
1004 : const char * pszDomain )
1005 :
1006 : {
1007 : /* ==================================================================== */
1008 : /* LocationInfo handling. */
1009 : /* ==================================================================== */
1010 4509 : if( pszDomain != NULL
1011 : && EQUAL(pszDomain,"LocationInfo")
1012 : && (EQUALN(pszName,"Pixel_",6) || EQUALN(pszName,"GeoPixel_",9)) )
1013 : {
1014 : int iPixel, iLine;
1015 :
1016 : /* -------------------------------------------------------------------- */
1017 : /* What pixel are we aiming at? */
1018 : /* -------------------------------------------------------------------- */
1019 1 : if( EQUALN(pszName,"Pixel_",6) )
1020 : {
1021 1 : if( sscanf( pszName+6, "%d_%d", &iPixel, &iLine ) != 2 )
1022 0 : return NULL;
1023 : }
1024 0 : else if( EQUALN(pszName,"GeoPixel_",9) )
1025 : {
1026 : double adfGeoTransform[6];
1027 : double adfInvGeoTransform[6];
1028 : double dfGeoX, dfGeoY;
1029 :
1030 0 : if( sscanf( pszName+9, "%lf_%lf", &dfGeoX, &dfGeoY ) != 2 )
1031 0 : return NULL;
1032 :
1033 0 : if( GetDataset() == NULL )
1034 0 : return NULL;
1035 :
1036 0 : if( GetDataset()->GetGeoTransform( adfGeoTransform ) != CE_None )
1037 0 : return NULL;
1038 :
1039 0 : if( !GDALInvGeoTransform( adfGeoTransform, adfInvGeoTransform ) )
1040 0 : return NULL;
1041 :
1042 : iPixel = (int) floor(
1043 0 : adfInvGeoTransform[0]
1044 0 : + adfInvGeoTransform[1] * dfGeoX
1045 0 : + adfInvGeoTransform[2] * dfGeoY );
1046 : iLine = (int) floor(
1047 0 : adfInvGeoTransform[3]
1048 0 : + adfInvGeoTransform[4] * dfGeoX
1049 0 : + adfInvGeoTransform[5] * dfGeoY );
1050 : }
1051 : else
1052 0 : return NULL;
1053 :
1054 1 : if( iPixel < 0 || iLine < 0
1055 : || iPixel >= GetXSize()
1056 : || iLine >= GetYSize() )
1057 0 : return NULL;
1058 :
1059 : /* -------------------------------------------------------------------- */
1060 : /* Find the file(s) at this location. */
1061 : /* -------------------------------------------------------------------- */
1062 1 : char **papszFileList = NULL;
1063 1 : int nListMaxSize = 0, nListSize = 0;
1064 : CPLHashSet* hSetFiles = CPLHashSetNew(CPLHashSetHashStr,
1065 : CPLHashSetEqualStr,
1066 1 : NULL);
1067 :
1068 2 : for( int iSource = 0; iSource < nSources; iSource++ )
1069 : {
1070 : int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
1071 : int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
1072 :
1073 1 : if (!papoSources[iSource]->IsSimpleSource())
1074 0 : continue;
1075 :
1076 1 : VRTSimpleSource *poSrc = (VRTSimpleSource *) papoSources[iSource];
1077 :
1078 1 : if( !poSrc->GetSrcDstWindow( iPixel, iLine, 1, 1, 1, 1,
1079 : &nReqXOff, &nReqYOff,
1080 : &nReqXSize, &nReqYSize,
1081 : &nOutXOff, &nOutYOff,
1082 : &nOutXSize, &nOutYSize ) )
1083 0 : continue;
1084 :
1085 : poSrc->GetFileList( &papszFileList, &nListSize, &nListMaxSize,
1086 1 : hSetFiles );
1087 : }
1088 :
1089 : /* -------------------------------------------------------------------- */
1090 : /* Format into XML. */
1091 : /* -------------------------------------------------------------------- */
1092 : int i;
1093 :
1094 1 : osLastLocationInfo = "<LocationInfo>";
1095 2 : for( i = 0; i < nListSize; i++ )
1096 : {
1097 1 : osLastLocationInfo += "<File>";
1098 1 : char* pszXMLEscaped = CPLEscapeString(papszFileList[i], -1, CPLES_XML);
1099 1 : osLastLocationInfo += pszXMLEscaped;
1100 1 : CPLFree(pszXMLEscaped);
1101 1 : osLastLocationInfo += "</File>";
1102 : }
1103 1 : osLastLocationInfo += "</LocationInfo>";
1104 :
1105 1 : CSLDestroy( papszFileList );
1106 1 : CPLHashSetDestroy( hSetFiles );
1107 :
1108 1 : return osLastLocationInfo.c_str();
1109 : }
1110 :
1111 : /* ==================================================================== */
1112 : /* Other domains. */
1113 : /* ==================================================================== */
1114 : else
1115 4508 : return GDALRasterBand::GetMetadataItem( pszName, pszDomain );
1116 : }
1117 :
1118 : /************************************************************************/
1119 : /* GetMetadata() */
1120 : /************************************************************************/
1121 :
1122 399 : char **VRTSourcedRasterBand::GetMetadata( const char *pszDomain )
1123 :
1124 : {
1125 : /* ==================================================================== */
1126 : /* vrt_sources domain handling. */
1127 : /* ==================================================================== */
1128 399 : if( pszDomain != NULL && EQUAL(pszDomain,"vrt_sources") )
1129 : {
1130 0 : char **papszSourceList = NULL;
1131 :
1132 : /* -------------------------------------------------------------------- */
1133 : /* Process SimpleSources. */
1134 : /* -------------------------------------------------------------------- */
1135 0 : for( int iSource = 0; iSource < nSources; iSource++ )
1136 : {
1137 : CPLXMLNode *psXMLSrc;
1138 : char *pszXML;
1139 :
1140 0 : psXMLSrc = papoSources[iSource]->SerializeToXML( NULL );
1141 0 : if( psXMLSrc == NULL )
1142 0 : continue;
1143 :
1144 0 : pszXML = CPLSerializeXMLTree( psXMLSrc );
1145 :
1146 : papszSourceList =
1147 : CSLSetNameValue( papszSourceList,
1148 0 : CPLSPrintf( "source_%d", iSource ), pszXML );
1149 0 : CPLFree( pszXML );
1150 0 : CPLDestroyXMLNode( psXMLSrc );
1151 : }
1152 :
1153 0 : return papszSourceList;
1154 : }
1155 :
1156 : /* ==================================================================== */
1157 : /* Other domains. */
1158 : /* ==================================================================== */
1159 : else
1160 399 : return GDALRasterBand::GetMetadata( pszDomain );
1161 : }
1162 :
1163 : /************************************************************************/
1164 : /* SetMetadataItem() */
1165 : /************************************************************************/
1166 :
1167 20 : CPLErr VRTSourcedRasterBand::SetMetadataItem( const char *pszName,
1168 : const char *pszValue,
1169 : const char *pszDomain )
1170 :
1171 : {
1172 : CPLDebug( "VRT", "VRTSourcedRasterBand::SetMetadataItem(%s,%s,%s)\n",
1173 20 : pszName, pszValue, pszDomain );
1174 :
1175 20 : if( pszDomain != NULL
1176 : && EQUAL(pszDomain,"new_vrt_sources") )
1177 : {
1178 1 : VRTDriver *poDriver = (VRTDriver *) GDALGetDriverByName( "VRT" );
1179 :
1180 1 : CPLXMLNode *psTree = CPLParseXMLString( pszValue );
1181 : VRTSource *poSource;
1182 :
1183 1 : if( psTree == NULL )
1184 0 : return CE_Failure;
1185 :
1186 1 : poSource = poDriver->ParseSource( psTree, NULL );
1187 1 : CPLDestroyXMLNode( psTree );
1188 :
1189 1 : if( poSource != NULL )
1190 1 : return AddSource( poSource );
1191 : else
1192 0 : return CE_Failure;
1193 : }
1194 19 : else if( pszDomain != NULL
1195 : && EQUAL(pszDomain,"vrt_sources") )
1196 : {
1197 : int iSource;
1198 1 : if (sscanf(pszName, "source_%d", &iSource) != 1 || iSource < 0 ||
1199 : iSource >= nSources)
1200 : {
1201 : CPLError(CE_Failure, CPLE_AppDefined,
1202 : "%s metadata item name is not recognized. "
1203 : "Should be between source_0 and source_%d",
1204 0 : pszName, nSources - 1);
1205 0 : return CE_Failure;
1206 : }
1207 :
1208 1 : VRTDriver *poDriver = (VRTDriver *) GDALGetDriverByName( "VRT" );
1209 :
1210 1 : CPLXMLNode *psTree = CPLParseXMLString( pszValue );
1211 : VRTSource *poSource;
1212 :
1213 1 : if( psTree == NULL )
1214 0 : return CE_Failure;
1215 :
1216 1 : poSource = poDriver->ParseSource( psTree, NULL );
1217 1 : CPLDestroyXMLNode( psTree );
1218 :
1219 1 : if( poSource != NULL )
1220 : {
1221 1 : delete papoSources[iSource];
1222 1 : papoSources[iSource] = poSource;
1223 1 : ((VRTDataset *)poDS)->SetNeedsFlush();
1224 1 : return CE_None;
1225 : }
1226 : else
1227 0 : return CE_Failure;
1228 : }
1229 : else
1230 18 : return VRTRasterBand::SetMetadataItem( pszName, pszValue, pszDomain );
1231 : }
1232 :
1233 : /************************************************************************/
1234 : /* SetMetadata() */
1235 : /************************************************************************/
1236 :
1237 179 : CPLErr VRTSourcedRasterBand::SetMetadata( char **papszNewMD, const char *pszDomain )
1238 :
1239 : {
1240 179 : if( pszDomain != NULL
1241 : && (EQUAL(pszDomain,"new_vrt_sources")
1242 : || EQUAL(pszDomain,"vrt_sources")) )
1243 : {
1244 4 : VRTDriver *poDriver = (VRTDriver *) GDALGetDriverByName( "VRT" );
1245 : CPLErr eErr;
1246 : int i;
1247 :
1248 4 : if( EQUAL(pszDomain,"vrt_sources") )
1249 : {
1250 4 : for( int i = 0; i < nSources; i++ )
1251 0 : delete papoSources[i];
1252 4 : CPLFree( papoSources );
1253 4 : papoSources = NULL;
1254 4 : nSources = 0;
1255 : }
1256 :
1257 16 : for( i = 0; i < CSLCount(papszNewMD); i++ )
1258 : {
1259 4 : const char *pszXML = CPLParseNameValue( papszNewMD[i], NULL );
1260 4 : CPLXMLNode *psTree = CPLParseXMLString( pszXML );
1261 : VRTSource *poSource;
1262 :
1263 4 : if( psTree == NULL )
1264 0 : return CE_Failure;
1265 :
1266 4 : poSource = poDriver->ParseSource( psTree, NULL );
1267 4 : CPLDestroyXMLNode( psTree );
1268 :
1269 4 : if( poSource != NULL )
1270 : {
1271 4 : eErr = AddSource( poSource );
1272 4 : if( eErr != CE_None )
1273 0 : return eErr;
1274 : }
1275 : else
1276 0 : return CE_Failure;
1277 : }
1278 :
1279 4 : return CE_None;
1280 : }
1281 : else
1282 175 : return VRTRasterBand::SetMetadata( papszNewMD, pszDomain );
1283 : }
1284 :
1285 : /************************************************************************/
1286 : /* GetFileList() */
1287 : /************************************************************************/
1288 :
1289 4 : void VRTSourcedRasterBand::GetFileList(char*** ppapszFileList, int *pnSize,
1290 : int *pnMaxSize, CPLHashSet* hSetFiles)
1291 : {
1292 8 : for( int i = 0; i < nSources; i++ )
1293 : {
1294 12 : papoSources[i]->GetFileList(ppapszFileList, pnSize,
1295 16 : pnMaxSize, hSetFiles);
1296 : }
1297 :
1298 : VRTRasterBand::GetFileList( ppapszFileList, pnSize,
1299 4 : pnMaxSize, hSetFiles);
1300 4 : }
1301 :
1302 : /************************************************************************/
1303 : /* CloseDependentDatasets() */
1304 : /************************************************************************/
1305 :
1306 2384 : int VRTSourcedRasterBand::CloseDependentDatasets()
1307 : {
1308 2384 : if (nSources == 0)
1309 212 : return FALSE;
1310 :
1311 7637 : for( int i = 0; i < nSources; i++ )
1312 5465 : delete papoSources[i];
1313 :
1314 2172 : CPLFree( papoSources );
1315 2172 : papoSources = NULL;
1316 2172 : nSources = 0;
1317 :
1318 2172 : return TRUE;
1319 : }
|