1 : /******************************************************************************
2 : * $Id: vrtsourcedrasterband.cpp 17852 2009-10-18 11:15:09Z 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 17852 2009-10-18 11:15:09Z rouault $");
35 :
36 : /************************************************************************/
37 : /* ==================================================================== */
38 : /* VRTSourcedRasterBand */
39 : /* ==================================================================== */
40 : /************************************************************************/
41 :
42 : /************************************************************************/
43 : /* VRTSourcedRasterBand() */
44 : /************************************************************************/
45 :
46 143 : VRTSourcedRasterBand::VRTSourcedRasterBand( GDALDataset *poDS, int nBand )
47 :
48 : {
49 143 : Initialize( poDS->GetRasterXSize(), poDS->GetRasterYSize() );
50 :
51 143 : this->poDS = poDS;
52 143 : this->nBand = nBand;
53 143 : }
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 114 : VRTSourcedRasterBand::VRTSourcedRasterBand( GDALDataset *poDS, int nBand,
73 : GDALDataType eType,
74 114 : int nXSize, int nYSize )
75 :
76 : {
77 114 : Initialize( nXSize, nYSize );
78 :
79 114 : this->poDS = poDS;
80 114 : this->nBand = nBand;
81 :
82 114 : eDataType = eType;
83 114 : }
84 :
85 : /************************************************************************/
86 : /* Initialize() */
87 : /************************************************************************/
88 :
89 257 : void VRTSourcedRasterBand::Initialize( int nXSize, int nYSize )
90 :
91 : {
92 257 : VRTRasterBand::Initialize( nXSize, nYSize );
93 :
94 257 : nSources = 0;
95 257 : papoSources = NULL;
96 257 : bEqualAreas = FALSE;
97 257 : bAlreadyInIRasterIO = FALSE;
98 257 : }
99 :
100 : /************************************************************************/
101 : /* ~VRTSourcedRasterBand() */
102 : /************************************************************************/
103 :
104 514 : VRTSourcedRasterBand::~VRTSourcedRasterBand()
105 :
106 : {
107 554 : for( int i = 0; i < nSources; i++ )
108 297 : delete papoSources[i];
109 :
110 257 : CPLFree( papoSources );
111 257 : nSources = 0;
112 514 : }
113 :
114 : /************************************************************************/
115 : /* IRasterIO() */
116 : /************************************************************************/
117 :
118 6051 : CPLErr VRTSourcedRasterBand::IRasterIO( GDALRWFlag eRWFlag,
119 : int nXOff, int nYOff, int nXSize, int nYSize,
120 : void * pData, int nBufXSize, int nBufYSize,
121 : GDALDataType eBufType,
122 : int nPixelSpace, int nLineSpace )
123 :
124 : {
125 : int iSource;
126 6051 : CPLErr eErr = CE_None;
127 :
128 6051 : if( eRWFlag == GF_Write )
129 : {
130 : CPLError( CE_Failure, CPLE_AppDefined,
131 0 : "Writing through VRTSourcedRasterBand is not supported." );
132 0 : return CE_Failure;
133 : }
134 :
135 : /* When using GDALProxyPoolDataset for sources, the recusion will not be */
136 : /* detected at VRT opening but when doing RasterIO. As the proxy pool will */
137 : /* return the already opened dataset, we can just test a member variable. */
138 6051 : if ( bAlreadyInIRasterIO )
139 : {
140 : CPLError( CE_Failure, CPLE_AppDefined,
141 : "VRTSourcedRasterBand::IRasterIO() called recursively on the same band. "
142 0 : "It looks like the VRT is referencing itself." );
143 0 : return CE_Failure;
144 : }
145 :
146 : /* -------------------------------------------------------------------- */
147 : /* Initialize the buffer to some background value. Use the */
148 : /* nodata value if available. */
149 : /* -------------------------------------------------------------------- */
150 6051 : if ( nPixelSpace == GDALGetDataTypeSize(eBufType)/8 &&
151 : (!bNoDataValueSet || dfNoDataValue == 0) )
152 : {
153 4432 : if (nLineSpace == nBufXSize * nPixelSpace)
154 : {
155 4430 : memset( pData, 0, nBufYSize * nLineSpace );
156 : }
157 : else
158 : {
159 : int iLine;
160 202 : for( iLine = 0; iLine < nBufYSize; iLine++ )
161 : {
162 200 : memset( ((GByte*)pData) + iLine * nLineSpace, 0, nBufXSize * nPixelSpace );
163 : }
164 : }
165 : }
166 1619 : else if ( !bEqualAreas || bNoDataValueSet )
167 : {
168 1619 : double dfWriteValue = 0.0;
169 : int iLine;
170 :
171 1619 : if( bNoDataValueSet )
172 1619 : dfWriteValue = dfNoDataValue;
173 :
174 5501 : for( iLine = 0; iLine < nBufYSize; iLine++ )
175 : {
176 : GDALCopyWords( &dfWriteValue, GDT_Float64, 0,
177 : ((GByte *)pData) + nLineSpace * iLine,
178 3882 : eBufType, nPixelSpace, nBufXSize );
179 : }
180 : }
181 :
182 :
183 : /* -------------------------------------------------------------------- */
184 : /* Do we have overviews that would be appropriate to satisfy */
185 : /* this request? */
186 : /* -------------------------------------------------------------------- */
187 6071 : if( (nBufXSize < nXSize || nBufYSize < nYSize)
188 20 : && GetOverviewCount() > 0 )
189 : {
190 0 : if( OverviewRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
191 : pData, nBufXSize, nBufYSize,
192 : eBufType, nPixelSpace, nLineSpace ) == CE_None )
193 0 : return CE_None;
194 : }
195 :
196 6051 : bAlreadyInIRasterIO = TRUE;
197 :
198 : /* -------------------------------------------------------------------- */
199 : /* Overlay each source in turn over top this. */
200 : /* -------------------------------------------------------------------- */
201 12613 : for( iSource = 0; eErr == CE_None && iSource < nSources; iSource++ )
202 : {
203 : eErr =
204 19686 : papoSources[iSource]->RasterIO( nXOff, nYOff, nXSize, nYSize,
205 : pData, nBufXSize, nBufYSize,
206 26248 : eBufType, nPixelSpace, nLineSpace);
207 : }
208 :
209 6051 : bAlreadyInIRasterIO = FALSE;
210 :
211 6051 : return eErr;
212 : }
213 :
214 : /************************************************************************/
215 : /* IReadBlock() */
216 : /************************************************************************/
217 :
218 0 : CPLErr VRTSourcedRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
219 : void * pImage )
220 :
221 : {
222 0 : int nPixelSize = GDALGetDataTypeSize(eDataType)/8;
223 : int nReadXSize, nReadYSize;
224 :
225 0 : if( (nBlockXOff+1) * nBlockXSize > GetXSize() )
226 0 : nReadXSize = GetXSize() - nBlockXOff * nBlockXSize;
227 : else
228 0 : nReadXSize = nBlockXSize;
229 :
230 0 : if( (nBlockYOff+1) * nBlockYSize > GetYSize() )
231 0 : nReadYSize = GetYSize() - nBlockYOff * nBlockYSize;
232 : else
233 0 : nReadYSize = nBlockYSize;
234 :
235 : return IRasterIO( GF_Read,
236 : nBlockXOff * nBlockXSize, nBlockYOff * nBlockYSize,
237 : nReadXSize, nReadYSize,
238 : pImage, nReadXSize, nReadYSize, eDataType,
239 0 : nPixelSize, nPixelSize * nBlockXSize );
240 : }
241 :
242 : /************************************************************************/
243 : /* AddSource() */
244 : /************************************************************************/
245 :
246 297 : CPLErr VRTSourcedRasterBand::AddSource( VRTSource *poNewSource )
247 :
248 : {
249 297 : nSources++;
250 :
251 : papoSources = (VRTSource **)
252 297 : CPLRealloc(papoSources, sizeof(void*) * nSources);
253 297 : papoSources[nSources-1] = poNewSource;
254 :
255 297 : ((VRTDataset *)poDS)->SetNeedsFlush();
256 :
257 297 : return CE_None;
258 : }
259 :
260 : /************************************************************************/
261 : /* VRTAddSource() */
262 : /************************************************************************/
263 :
264 : /**
265 : * @see VRTSourcedRasterBand::AddSource().
266 : */
267 :
268 0 : CPLErr CPL_STDCALL VRTAddSource( VRTSourcedRasterBandH hVRTBand,
269 : VRTSourceH hNewSource )
270 : {
271 0 : VALIDATE_POINTER1( hVRTBand, "VRTAddSource", CE_Failure );
272 :
273 : return ((VRTSourcedRasterBand *) hVRTBand)->
274 0 : AddSource( (VRTSource *)hNewSource );
275 : }
276 :
277 : /************************************************************************/
278 : /* XMLInit() */
279 : /************************************************************************/
280 :
281 143 : CPLErr VRTSourcedRasterBand::XMLInit( CPLXMLNode * psTree,
282 : const char *pszVRTPath )
283 :
284 : {
285 : CPLErr eErr;
286 :
287 143 : eErr = VRTRasterBand::XMLInit( psTree, pszVRTPath );
288 143 : if( eErr != CE_None )
289 0 : return eErr;
290 :
291 : /* -------------------------------------------------------------------- */
292 : /* Validate a bit. */
293 : /* -------------------------------------------------------------------- */
294 143 : if( psTree == NULL || psTree->eType != CXT_Element
295 : || (!EQUAL(psTree->pszValue,"VRTSourcedRasterBand")
296 : && !EQUAL(psTree->pszValue,"VRTRasterBand")
297 : && !EQUAL(psTree->pszValue,"VRTDerivedRasterBand")) )
298 : {
299 : CPLError( CE_Failure, CPLE_AppDefined,
300 0 : "Invalid node passed to VRTSourcedRasterBand::XMLInit()." );
301 0 : return CE_Failure;
302 : }
303 :
304 : /* -------------------------------------------------------------------- */
305 : /* Process sources. */
306 : /* -------------------------------------------------------------------- */
307 : CPLXMLNode *psChild;
308 143 : VRTDriver *poDriver = (VRTDriver *) GDALGetDriverByName( "VRT" );
309 :
310 819 : for( psChild = psTree->psChild;
311 : psChild != NULL && poDriver != NULL;
312 : psChild = psChild->psNext)
313 : {
314 : VRTSource *poSource;
315 :
316 677 : if( psChild->eType != CXT_Element )
317 288 : continue;
318 :
319 389 : CPLErrorReset();
320 389 : poSource = poDriver->ParseSource( psChild, pszVRTPath );
321 389 : if( poSource != NULL )
322 183 : AddSource( poSource );
323 206 : else if( CPLGetLastErrorType() != CE_None )
324 1 : return CE_Failure;
325 : }
326 :
327 : /* -------------------------------------------------------------------- */
328 : /* Done. */
329 : /* -------------------------------------------------------------------- */
330 142 : if( nSources == 0 )
331 : CPLDebug( "VRT", "No valid sources found for band in VRT file:\n%s",
332 0 : pszVRTPath );
333 :
334 142 : return CE_None;
335 : }
336 :
337 : /************************************************************************/
338 : /* SerializeToXML() */
339 : /************************************************************************/
340 :
341 76 : CPLXMLNode *VRTSourcedRasterBand::SerializeToXML( const char *pszVRTPath )
342 :
343 : {
344 : CPLXMLNode *psTree;
345 :
346 76 : psTree = VRTRasterBand::SerializeToXML( pszVRTPath );
347 :
348 : /* -------------------------------------------------------------------- */
349 : /* Process Sources. */
350 : /* -------------------------------------------------------------------- */
351 152 : for( int iSource = 0; iSource < nSources; iSource++ )
352 : {
353 : CPLXMLNode *psXMLSrc;
354 :
355 76 : psXMLSrc = papoSources[iSource]->SerializeToXML( pszVRTPath );
356 :
357 76 : if( psXMLSrc != NULL )
358 76 : CPLAddXMLChild( psTree, psXMLSrc );
359 : }
360 :
361 76 : return psTree;
362 : }
363 :
364 : /************************************************************************/
365 : /* AddSimpleSource() */
366 : /************************************************************************/
367 :
368 94 : CPLErr VRTSourcedRasterBand::AddSimpleSource( GDALRasterBand *poSrcBand,
369 : int nSrcXOff, int nSrcYOff,
370 : int nSrcXSize, int nSrcYSize,
371 : int nDstXOff, int nDstYOff,
372 : int nDstXSize, int nDstYSize,
373 : const char *pszResampling,
374 : double dfNoDataValue )
375 :
376 : {
377 : /* -------------------------------------------------------------------- */
378 : /* Default source and dest rectangles. */
379 : /* -------------------------------------------------------------------- */
380 94 : if( nSrcYSize == -1 )
381 : {
382 30 : nSrcXOff = 0;
383 30 : nSrcYOff = 0;
384 30 : nSrcXSize = poSrcBand->GetXSize();
385 30 : nSrcYSize = poSrcBand->GetYSize();
386 : }
387 :
388 94 : if( nDstYSize == -1 )
389 : {
390 30 : nDstXOff = 0;
391 30 : nDstYOff = 0;
392 30 : nDstXSize = nRasterXSize;
393 30 : nDstYSize = nRasterYSize;
394 : }
395 :
396 : /* -------------------------------------------------------------------- */
397 : /* Create source. */
398 : /* -------------------------------------------------------------------- */
399 : VRTSimpleSource *poSimpleSource;
400 :
401 94 : if( pszResampling != NULL && EQUALN(pszResampling,"aver",4) )
402 0 : poSimpleSource = new VRTAveragedSource();
403 : else
404 : {
405 94 : poSimpleSource = new VRTSimpleSource();
406 94 : if( dfNoDataValue != VRT_NODATA_UNSET )
407 : CPLError(
408 : CE_Warning, CPLE_AppDefined,
409 : "NODATA setting not currently supported for nearest\n"
410 0 : "neighbour sampled simple sources on Virtual Datasources." );
411 : }
412 :
413 94 : poSimpleSource->SetSrcBand( poSrcBand );
414 94 : poSimpleSource->SetSrcWindow( nSrcXOff, nSrcYOff, nSrcXSize, nSrcYSize );
415 94 : poSimpleSource->SetDstWindow( nDstXOff, nDstYOff, nDstXSize, nDstYSize );
416 :
417 94 : if( dfNoDataValue != VRT_NODATA_UNSET )
418 0 : poSimpleSource->SetNoDataValue( dfNoDataValue );
419 :
420 : /* -------------------------------------------------------------------- */
421 : /* Default source and dest rectangles. */
422 : /* -------------------------------------------------------------------- */
423 94 : if ( nSrcXOff == nDstXOff && nSrcYOff == nDstYOff &&
424 : nSrcXSize == nDstXSize && nSrcYSize == nRasterYSize )
425 58 : bEqualAreas = TRUE;
426 :
427 : /* -------------------------------------------------------------------- */
428 : /* If we can get the associated GDALDataset, add a reference to it.*/
429 : /* -------------------------------------------------------------------- */
430 94 : if( poSrcBand->GetDataset() != NULL )
431 94 : poSrcBand->GetDataset()->Reference();
432 :
433 : /* -------------------------------------------------------------------- */
434 : /* add to list. */
435 : /* -------------------------------------------------------------------- */
436 94 : return AddSource( poSimpleSource );
437 : }
438 :
439 : /************************************************************************/
440 : /* VRTAddSimpleSource() */
441 : /************************************************************************/
442 :
443 : /**
444 : * @see VRTSourcedRasterBand::AddSimpleSource().
445 : */
446 :
447 34 : CPLErr CPL_STDCALL VRTAddSimpleSource( VRTSourcedRasterBandH hVRTBand,
448 : GDALRasterBandH hSrcBand,
449 : int nSrcXOff, int nSrcYOff,
450 : int nSrcXSize, int nSrcYSize,
451 : int nDstXOff, int nDstYOff,
452 : int nDstXSize, int nDstYSize,
453 : const char *pszResampling,
454 : double dfNoDataValue )
455 : {
456 34 : VALIDATE_POINTER1( hVRTBand, "VRTAddSimpleSource", CE_Failure );
457 :
458 : return ((VRTSourcedRasterBand *) hVRTBand)->AddSimpleSource(
459 : (GDALRasterBand *)hSrcBand,
460 : nSrcXOff, nSrcYOff,
461 : nSrcXSize, nSrcYSize,
462 : nDstXOff, nDstYOff,
463 : nDstXSize, nDstYSize,
464 34 : pszResampling, dfNoDataValue );
465 : }
466 :
467 : /************************************************************************/
468 : /* AddComplexSource() */
469 : /************************************************************************/
470 :
471 18 : CPLErr VRTSourcedRasterBand::AddComplexSource( GDALRasterBand *poSrcBand,
472 : int nSrcXOff, int nSrcYOff,
473 : int nSrcXSize, int nSrcYSize,
474 : int nDstXOff, int nDstYOff,
475 : int nDstXSize, int nDstYSize,
476 : double dfScaleOff,
477 : double dfScaleRatio,
478 : double dfNoDataValue,
479 : int nColorTableComponent)
480 :
481 : {
482 : /* -------------------------------------------------------------------- */
483 : /* Default source and dest rectangles. */
484 : /* -------------------------------------------------------------------- */
485 18 : if( nSrcYSize == -1 )
486 : {
487 0 : nSrcXOff = 0;
488 0 : nSrcYOff = 0;
489 0 : nSrcXSize = poSrcBand->GetXSize();
490 0 : nSrcYSize = poSrcBand->GetYSize();
491 : }
492 :
493 18 : if( nDstYSize == -1 )
494 : {
495 0 : nDstXOff = 0;
496 0 : nDstYOff = 0;
497 0 : nDstXSize = nRasterXSize;
498 0 : nDstYSize = nRasterYSize;
499 : }
500 :
501 : /* -------------------------------------------------------------------- */
502 : /* Create source. */
503 : /* -------------------------------------------------------------------- */
504 : VRTComplexSource *poSource;
505 :
506 18 : poSource = new VRTComplexSource();
507 :
508 18 : poSource->SetSrcBand( poSrcBand );
509 18 : poSource->SetSrcWindow( nSrcXOff, nSrcYOff, nSrcXSize, nSrcYSize );
510 18 : poSource->SetDstWindow( nDstXOff, nDstYOff, nDstXSize, nDstYSize );
511 :
512 : /* -------------------------------------------------------------------- */
513 : /* Set complex parameters. */
514 : /* -------------------------------------------------------------------- */
515 18 : if( dfNoDataValue != VRT_NODATA_UNSET )
516 8 : poSource->SetNoDataValue( dfNoDataValue );
517 :
518 18 : if( dfScaleOff != 0.0 || dfScaleRatio != 1.0 )
519 : {
520 0 : poSource->bDoScaling = TRUE;
521 0 : poSource->dfScaleOff = dfScaleOff;
522 0 : poSource->dfScaleRatio = dfScaleRatio;
523 :
524 : }
525 :
526 18 : poSource->nColorTableComponent = nColorTableComponent;
527 :
528 : /* -------------------------------------------------------------------- */
529 : /* If we can get the associated GDALDataset, add a reference to it.*/
530 : /* -------------------------------------------------------------------- */
531 18 : if( poSrcBand->GetDataset() != NULL )
532 18 : poSrcBand->GetDataset()->Reference();
533 :
534 : /* -------------------------------------------------------------------- */
535 : /* add to list. */
536 : /* -------------------------------------------------------------------- */
537 18 : return AddSource( poSource );
538 : }
539 :
540 : /************************************************************************/
541 : /* VRTAddComplexSource() */
542 : /************************************************************************/
543 :
544 : /**
545 : * @see VRTSourcedRasterBand::AddComplexSource().
546 : */
547 :
548 8 : CPLErr CPL_STDCALL VRTAddComplexSource( VRTSourcedRasterBandH hVRTBand,
549 : GDALRasterBandH hSrcBand,
550 : int nSrcXOff, int nSrcYOff,
551 : int nSrcXSize, int nSrcYSize,
552 : int nDstXOff, int nDstYOff,
553 : int nDstXSize, int nDstYSize,
554 : double dfScaleOff,
555 : double dfScaleRatio,
556 : double dfNoDataValue )
557 : {
558 8 : VALIDATE_POINTER1( hVRTBand, "VRTAddComplexSource", CE_Failure );
559 :
560 : return ((VRTSourcedRasterBand *) hVRTBand)->AddComplexSource(
561 : (GDALRasterBand *)hSrcBand,
562 : nSrcXOff, nSrcYOff,
563 : nSrcXSize, nSrcYSize,
564 : nDstXOff, nDstYOff,
565 : nDstXSize, nDstYSize,
566 : dfScaleOff, dfScaleRatio,
567 8 : dfNoDataValue );
568 : }
569 :
570 : /************************************************************************/
571 : /* AddFuncSource() */
572 : /************************************************************************/
573 :
574 0 : CPLErr VRTSourcedRasterBand::AddFuncSource( VRTImageReadFunc pfnReadFunc,
575 : void *pCBData, double dfNoDataValue )
576 :
577 : {
578 : /* -------------------------------------------------------------------- */
579 : /* Create source. */
580 : /* -------------------------------------------------------------------- */
581 0 : VRTFuncSource *poFuncSource = new VRTFuncSource;
582 :
583 0 : poFuncSource->fNoDataValue = (float) dfNoDataValue;
584 0 : poFuncSource->pfnReadFunc = pfnReadFunc;
585 0 : poFuncSource->pCBData = pCBData;
586 0 : poFuncSource->eType = GetRasterDataType();
587 :
588 : /* -------------------------------------------------------------------- */
589 : /* add to list. */
590 : /* -------------------------------------------------------------------- */
591 0 : return AddSource( poFuncSource );
592 : }
593 :
594 : /************************************************************************/
595 : /* VRTAddFuncSource() */
596 : /************************************************************************/
597 :
598 : /**
599 : * @see VRTSourcedRasterBand::AddFuncSource().
600 : */
601 :
602 0 : CPLErr CPL_STDCALL VRTAddFuncSource( VRTSourcedRasterBandH hVRTBand,
603 : VRTImageReadFunc pfnReadFunc,
604 : void *pCBData, double dfNoDataValue )
605 : {
606 0 : VALIDATE_POINTER1( hVRTBand, "VRTAddFuncSource", CE_Failure );
607 :
608 : return ((VRTSourcedRasterBand *) hVRTBand)->
609 0 : AddFuncSource( pfnReadFunc, pCBData, dfNoDataValue );
610 : }
611 :
612 : /************************************************************************/
613 : /* GetMetadata() */
614 : /************************************************************************/
615 :
616 238 : char **VRTSourcedRasterBand::GetMetadata( const char *pszDomain )
617 :
618 : {
619 238 : if( pszDomain != NULL && EQUAL(pszDomain,"vrt_sources") )
620 : {
621 0 : char **papszSourceList = NULL;
622 :
623 : /* -------------------------------------------------------------------- */
624 : /* Process SimpleSources. */
625 : /* -------------------------------------------------------------------- */
626 0 : for( int iSource = 0; iSource < nSources; iSource++ )
627 : {
628 : CPLXMLNode *psXMLSrc;
629 : char *pszXML;
630 :
631 0 : psXMLSrc = papoSources[iSource]->SerializeToXML( NULL );
632 0 : if( psXMLSrc == NULL )
633 0 : continue;
634 :
635 0 : pszXML = CPLSerializeXMLTree( psXMLSrc );
636 :
637 : papszSourceList =
638 : CSLSetNameValue( papszSourceList,
639 0 : CPLSPrintf( "source_%d", iSource ), pszXML );
640 0 : CPLFree( pszXML );
641 0 : CPLDestroyXMLNode( psXMLSrc );
642 : }
643 :
644 0 : return papszSourceList;
645 : }
646 : else
647 238 : return GDALRasterBand::GetMetadata( pszDomain );
648 : }
649 :
650 : /************************************************************************/
651 : /* SetMetadataItem() */
652 : /************************************************************************/
653 :
654 12 : CPLErr VRTSourcedRasterBand::SetMetadataItem( const char *pszName,
655 : const char *pszValue,
656 : const char *pszDomain )
657 :
658 : {
659 : CPLDebug( "VRT", "VRTSourcedRasterBand::SetMetadataItem(%s,%s,%s)\n",
660 12 : pszName, pszValue, pszDomain );
661 :
662 12 : if( pszDomain != NULL
663 : && EQUAL(pszDomain,"new_vrt_sources") )
664 : {
665 1 : VRTDriver *poDriver = (VRTDriver *) GDALGetDriverByName( "VRT" );
666 :
667 1 : CPLXMLNode *psTree = CPLParseXMLString( pszValue );
668 : VRTSource *poSource;
669 :
670 1 : if( psTree == NULL )
671 0 : return CE_Failure;
672 :
673 1 : poSource = poDriver->ParseSource( psTree, NULL );
674 1 : CPLDestroyXMLNode( psTree );
675 :
676 1 : if( poSource != NULL )
677 1 : return AddSource( poSource );
678 : else
679 0 : return CE_Failure;
680 : }
681 11 : else if( pszDomain != NULL
682 : && EQUAL(pszDomain,"vrt_sources") )
683 : {
684 : int iSource;
685 1 : if (sscanf(pszName, "source_%d", &iSource) != 1 || iSource < 0 ||
686 : iSource >= nSources)
687 : {
688 : CPLError(CE_Failure, CPLE_AppDefined,
689 : "%s metadata item name is not recognized. "
690 : "Should be between source_0 and source_%d",
691 0 : pszName, nSources - 1);
692 0 : return CE_Failure;
693 : }
694 :
695 1 : VRTDriver *poDriver = (VRTDriver *) GDALGetDriverByName( "VRT" );
696 :
697 1 : CPLXMLNode *psTree = CPLParseXMLString( pszValue );
698 : VRTSource *poSource;
699 :
700 1 : if( psTree == NULL )
701 0 : return CE_Failure;
702 :
703 1 : poSource = poDriver->ParseSource( psTree, NULL );
704 1 : CPLDestroyXMLNode( psTree );
705 :
706 1 : if( poSource != NULL )
707 : {
708 1 : delete papoSources[iSource];
709 1 : papoSources[iSource] = poSource;
710 1 : ((VRTDataset *)poDS)->SetNeedsFlush();
711 1 : return CE_None;
712 : }
713 : else
714 0 : return CE_Failure;
715 : }
716 : else
717 10 : return VRTRasterBand::SetMetadataItem( pszName, pszValue, pszDomain );
718 : }
719 :
720 : /************************************************************************/
721 : /* SetMetadata() */
722 : /************************************************************************/
723 :
724 44 : CPLErr VRTSourcedRasterBand::SetMetadata( char **papszNewMD, const char *pszDomain )
725 :
726 : {
727 44 : if( pszDomain != NULL
728 : && (EQUAL(pszDomain,"new_vrt_sources")
729 : || EQUAL(pszDomain,"vrt_sources")) )
730 : {
731 1 : VRTDriver *poDriver = (VRTDriver *) GDALGetDriverByName( "VRT" );
732 : CPLErr eErr;
733 : int i;
734 :
735 1 : if( EQUAL(pszDomain,"vrt_sources") )
736 : {
737 1 : for( int i = 0; i < nSources; i++ )
738 0 : delete papoSources[i];
739 1 : CPLFree( papoSources );
740 1 : papoSources = NULL;
741 1 : nSources = 0;
742 : }
743 :
744 4 : for( i = 0; i < CSLCount(papszNewMD); i++ )
745 : {
746 1 : const char *pszXML = CPLParseNameValue( papszNewMD[i], NULL );
747 1 : CPLXMLNode *psTree = CPLParseXMLString( pszXML );
748 : VRTSource *poSource;
749 :
750 1 : if( psTree == NULL )
751 0 : return CE_Failure;
752 :
753 1 : poSource = poDriver->ParseSource( psTree, NULL );
754 1 : CPLDestroyXMLNode( psTree );
755 :
756 1 : if( poSource != NULL )
757 : {
758 1 : eErr = AddSource( poSource );
759 1 : if( eErr != CE_None )
760 0 : return eErr;
761 : }
762 : else
763 0 : return CE_Failure;
764 : }
765 :
766 1 : return CE_None;
767 : }
768 : else
769 43 : return VRTRasterBand::SetMetadata( papszNewMD, pszDomain );
770 : }
771 :
772 : /************************************************************************/
773 : /* GetFileList() */
774 : /************************************************************************/
775 :
776 0 : void VRTSourcedRasterBand::GetFileList(char*** ppapszFileList, int *pnSize,
777 : int *pnMaxSize, CPLHashSet* hSetFiles)
778 : {
779 0 : for( int i = 0; i < nSources; i++ )
780 : {
781 0 : papoSources[i]->GetFileList(ppapszFileList, pnSize,
782 0 : pnMaxSize, hSetFiles);
783 : }
784 0 : }
|