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