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