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