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 349 : VRTSourcedRasterBand::VRTSourcedRasterBand( GDALDataset *poDS, int nBand )
47 :
48 : {
49 349 : Initialize( poDS->GetRasterXSize(), poDS->GetRasterYSize() );
50 :
51 349 : this->poDS = poDS;
52 349 : this->nBand = nBand;
53 349 : }
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 299 : VRTSourcedRasterBand::VRTSourcedRasterBand( GDALDataset *poDS, int nBand,
73 : GDALDataType eType,
74 299 : int nXSize, int nYSize )
75 :
76 : {
77 299 : Initialize( nXSize, nYSize );
78 :
79 299 : this->poDS = poDS;
80 299 : this->nBand = nBand;
81 :
82 299 : eDataType = eType;
83 299 : }
84 :
85 : /************************************************************************/
86 : /* Initialize() */
87 : /************************************************************************/
88 :
89 648 : void VRTSourcedRasterBand::Initialize( int nXSize, int nYSize )
90 :
91 : {
92 648 : VRTRasterBand::Initialize( nXSize, nYSize );
93 :
94 648 : nSources = 0;
95 648 : papoSources = NULL;
96 648 : bEqualAreas = FALSE;
97 648 : bAntiRecursionFlag = FALSE;
98 648 : }
99 :
100 : /************************************************************************/
101 : /* ~VRTSourcedRasterBand() */
102 : /************************************************************************/
103 :
104 648 : VRTSourcedRasterBand::~VRTSourcedRasterBand()
105 :
106 : {
107 648 : CloseDependentDatasets();
108 648 : }
109 :
110 : /************************************************************************/
111 : /* IRasterIO() */
112 : /************************************************************************/
113 :
114 10728 : 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 10728 : CPLErr eErr = CE_None;
123 :
124 10728 : 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 10728 : 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 10748 : if( (nBufXSize < nXSize || nBufYSize < nYSize)
147 20 : && 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 10728 : if ( nPixelSpace == GDALGetDataTypeSize(eBufType)/8 &&
160 : (!bNoDataValueSet || (!CPLIsNan(dfNoDataValue) && dfNoDataValue == 0)) )
161 : {
162 9097 : if (nLineSpace == nBufXSize * nPixelSpace)
163 : {
164 9083 : memset( pData, 0, nBufYSize * nLineSpace );
165 : }
166 : else
167 : {
168 : int iLine;
169 1538 : for( iLine = 0; iLine < nBufYSize; iLine++ )
170 : {
171 1524 : memset( ((GByte*)pData) + iLine * nLineSpace, 0, nBufXSize * nPixelSpace );
172 : }
173 : }
174 : }
175 1631 : else if ( !bEqualAreas || bNoDataValueSet )
176 : {
177 1631 : double dfWriteValue = 0.0;
178 : int iLine;
179 :
180 1631 : if( bNoDataValueSet )
181 1631 : dfWriteValue = dfNoDataValue;
182 :
183 5544 : for( iLine = 0; iLine < nBufYSize; iLine++ )
184 : {
185 : GDALCopyWords( &dfWriteValue, GDT_Float64, 0,
186 : ((GByte *)pData) + nLineSpace * iLine,
187 3913 : eBufType, nPixelSpace, nBufXSize );
188 : }
189 : }
190 :
191 :
192 : /* -------------------------------------------------------------------- */
193 : /* Do we have overviews that would be appropriate to satisfy */
194 : /* this request? */
195 : /* -------------------------------------------------------------------- */
196 10748 : if( (nBufXSize < nXSize || nBufYSize < nYSize)
197 20 : && 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 10728 : bAntiRecursionFlag = TRUE;
206 :
207 : /* -------------------------------------------------------------------- */
208 : /* Overlay each source in turn over top this. */
209 : /* -------------------------------------------------------------------- */
210 24157 : for( iSource = 0; eErr == CE_None && iSource < nSources; iSource++ )
211 : {
212 : eErr =
213 40287 : papoSources[iSource]->RasterIO( nXOff, nYOff, nXSize, nYSize,
214 : pData, nBufXSize, nBufYSize,
215 53716 : eBufType, nPixelSpace, nLineSpace);
216 : }
217 :
218 10728 : bAntiRecursionFlag = FALSE;
219 :
220 10728 : return eErr;
221 : }
222 :
223 : /************************************************************************/
224 : /* IReadBlock() */
225 : /************************************************************************/
226 :
227 54 : CPLErr VRTSourcedRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
228 : void * pImage )
229 :
230 : {
231 54 : int nPixelSize = GDALGetDataTypeSize(eDataType)/8;
232 : int nReadXSize, nReadYSize;
233 :
234 54 : if( (nBlockXOff+1) * nBlockXSize > GetXSize() )
235 12 : nReadXSize = GetXSize() - nBlockXOff * nBlockXSize;
236 : else
237 42 : nReadXSize = nBlockXSize;
238 :
239 54 : if( (nBlockYOff+1) * nBlockYSize > GetYSize() )
240 16 : nReadYSize = GetYSize() - nBlockYOff * nBlockYSize;
241 : else
242 38 : nReadYSize = nBlockYSize;
243 :
244 : return IRasterIO( GF_Read,
245 : nBlockXOff * nBlockXSize, nBlockYOff * nBlockYSize,
246 : nReadXSize, nReadYSize,
247 : pImage, nReadXSize, nReadYSize, eDataType,
248 54 : nPixelSize, nPixelSize * nBlockXSize );
249 : }
250 :
251 : /************************************************************************/
252 : /* GetMinimum() */
253 : /************************************************************************/
254 :
255 10 : double VRTSourcedRasterBand::GetMinimum( int *pbSuccess )
256 : {
257 10 : const char *pszValue = NULL;
258 :
259 10 : if( (pszValue = GetMetadataItem("STATISTICS_MINIMUM")) != NULL )
260 : {
261 1 : if( pbSuccess != NULL )
262 1 : *pbSuccess = TRUE;
263 :
264 1 : return CPLAtofM(pszValue);
265 : }
266 :
267 9 : 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 9 : bAntiRecursionFlag = TRUE;
277 :
278 9 : double dfMin = 0;
279 10 : for( int iSource = 0; iSource < nSources; iSource++ )
280 : {
281 9 : int bSuccess = FALSE;
282 9 : double dfSourceMin = papoSources[iSource]->GetMinimum(GetXSize(), GetYSize(), &bSuccess);
283 9 : if (!bSuccess)
284 : {
285 8 : dfMin = GDALRasterBand::GetMinimum(pbSuccess);
286 8 : bAntiRecursionFlag = FALSE;
287 8 : return dfMin;
288 : }
289 :
290 1 : if (iSource == 0 || dfSourceMin < dfMin)
291 1 : dfMin = dfSourceMin;
292 : }
293 :
294 1 : bAntiRecursionFlag = FALSE;
295 :
296 1 : if( pbSuccess != NULL )
297 1 : *pbSuccess = TRUE;
298 :
299 1 : return dfMin;
300 : }
301 :
302 : /************************************************************************/
303 : /* GetMaximum() */
304 : /************************************************************************/
305 :
306 10 : double VRTSourcedRasterBand::GetMaximum(int *pbSuccess )
307 : {
308 10 : const char *pszValue = NULL;
309 :
310 10 : if( (pszValue = GetMetadataItem("STATISTICS_MAXIMUM")) != NULL )
311 : {
312 1 : if( pbSuccess != NULL )
313 1 : *pbSuccess = TRUE;
314 :
315 1 : return CPLAtofM(pszValue);
316 : }
317 :
318 9 : 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 9 : bAntiRecursionFlag = TRUE;
328 :
329 9 : double dfMax = 0;
330 10 : for( int iSource = 0; iSource < nSources; iSource++ )
331 : {
332 9 : int bSuccess = FALSE;
333 9 : double dfSourceMax = papoSources[iSource]->GetMaximum(GetXSize(), GetYSize(), &bSuccess);
334 9 : if (!bSuccess)
335 : {
336 8 : dfMax = GDALRasterBand::GetMaximum(pbSuccess);
337 8 : bAntiRecursionFlag = FALSE;
338 8 : return dfMax;
339 : }
340 :
341 1 : if (iSource == 0 || dfSourceMax > dfMax)
342 1 : dfMax = dfSourceMax;
343 : }
344 :
345 1 : bAntiRecursionFlag = FALSE;
346 :
347 1 : if( pbSuccess != NULL )
348 1 : *pbSuccess = TRUE;
349 :
350 1 : return dfMax;
351 : }
352 :
353 :
354 : /************************************************************************/
355 : /* AddSource() */
356 : /************************************************************************/
357 :
358 629 : CPLErr VRTSourcedRasterBand::AddSource( VRTSource *poNewSource )
359 :
360 : {
361 629 : nSources++;
362 :
363 : papoSources = (VRTSource **)
364 629 : CPLRealloc(papoSources, sizeof(void*) * nSources);
365 629 : papoSources[nSources-1] = poNewSource;
366 :
367 629 : ((VRTDataset *)poDS)->SetNeedsFlush();
368 :
369 629 : 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 345 : CPLErr VRTSourcedRasterBand::XMLInit( CPLXMLNode * psTree,
394 : const char *pszVRTPath )
395 :
396 : {
397 : CPLErr eErr;
398 :
399 345 : eErr = VRTRasterBand::XMLInit( psTree, pszVRTPath );
400 345 : if( eErr != CE_None )
401 0 : return eErr;
402 :
403 : /* -------------------------------------------------------------------- */
404 : /* Validate a bit. */
405 : /* -------------------------------------------------------------------- */
406 345 : 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 345 : VRTDriver *poDriver = (VRTDriver *) GDALGetDriverByName( "VRT" );
421 :
422 1817 : for( psChild = psTree->psChild;
423 : psChild != NULL && poDriver != NULL;
424 : psChild = psChild->psNext)
425 : {
426 : VRTSource *poSource;
427 :
428 1473 : if( psChild->eType != CXT_Element )
429 682 : continue;
430 :
431 791 : CPLErrorReset();
432 791 : poSource = poDriver->ParseSource( psChild, pszVRTPath );
433 791 : if( poSource != NULL )
434 330 : AddSource( poSource );
435 461 : else if( CPLGetLastErrorType() != CE_None )
436 1 : return CE_Failure;
437 : }
438 :
439 : /* -------------------------------------------------------------------- */
440 : /* Done. */
441 : /* -------------------------------------------------------------------- */
442 344 : if( nSources == 0 )
443 : CPLDebug( "VRT", "No valid sources found for band in VRT file:\n%s",
444 55 : pszVRTPath );
445 :
446 344 : return CE_None;
447 : }
448 :
449 : /************************************************************************/
450 : /* SerializeToXML() */
451 : /************************************************************************/
452 :
453 211 : CPLXMLNode *VRTSourcedRasterBand::SerializeToXML( const char *pszVRTPath )
454 :
455 : {
456 : CPLXMLNode *psTree;
457 :
458 211 : psTree = VRTRasterBand::SerializeToXML( pszVRTPath );
459 :
460 : /* -------------------------------------------------------------------- */
461 : /* Process Sources. */
462 : /* -------------------------------------------------------------------- */
463 392 : for( int iSource = 0; iSource < nSources; iSource++ )
464 : {
465 : CPLXMLNode *psXMLSrc;
466 :
467 181 : psXMLSrc = papoSources[iSource]->SerializeToXML( pszVRTPath );
468 :
469 181 : if( psXMLSrc != NULL )
470 181 : CPLAddXMLChild( psTree, psXMLSrc );
471 : }
472 :
473 211 : return psTree;
474 : }
475 :
476 : /************************************************************************/
477 : /* AddSimpleSource() */
478 : /************************************************************************/
479 :
480 265 : 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 265 : if( nSrcYSize == -1 )
493 : {
494 101 : nSrcXOff = 0;
495 101 : nSrcYOff = 0;
496 101 : nSrcXSize = poSrcBand->GetXSize();
497 101 : nSrcYSize = poSrcBand->GetYSize();
498 : }
499 :
500 265 : if( nDstYSize == -1 )
501 : {
502 101 : nDstXOff = 0;
503 101 : nDstYOff = 0;
504 101 : nDstXSize = nRasterXSize;
505 101 : nDstYSize = nRasterYSize;
506 : }
507 :
508 : /* -------------------------------------------------------------------- */
509 : /* Create source. */
510 : /* -------------------------------------------------------------------- */
511 : VRTSimpleSource *poSimpleSource;
512 :
513 265 : if( pszResampling != NULL && EQUALN(pszResampling,"aver",4) )
514 0 : poSimpleSource = new VRTAveragedSource();
515 : else
516 : {
517 265 : poSimpleSource = new VRTSimpleSource();
518 265 : 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 265 : poSimpleSource->SetSrcBand( poSrcBand );
526 265 : poSimpleSource->SetSrcWindow( nSrcXOff, nSrcYOff, nSrcXSize, nSrcYSize );
527 265 : poSimpleSource->SetDstWindow( nDstXOff, nDstYOff, nDstXSize, nDstYSize );
528 :
529 265 : if( dfNoDataValue != VRT_NODATA_UNSET )
530 0 : poSimpleSource->SetNoDataValue( dfNoDataValue );
531 :
532 : /* -------------------------------------------------------------------- */
533 : /* Default source and dest rectangles. */
534 : /* -------------------------------------------------------------------- */
535 265 : if ( nSrcXOff == nDstXOff && nSrcYOff == nDstYOff &&
536 : nSrcXSize == nDstXSize && nSrcYSize == nRasterYSize )
537 192 : bEqualAreas = TRUE;
538 :
539 : /* -------------------------------------------------------------------- */
540 : /* If we can get the associated GDALDataset, add a reference to it.*/
541 : /* -------------------------------------------------------------------- */
542 265 : if( poSrcBand->GetDataset() != NULL )
543 265 : poSrcBand->GetDataset()->Reference();
544 :
545 : /* -------------------------------------------------------------------- */
546 : /* add to list. */
547 : /* -------------------------------------------------------------------- */
548 265 : 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 5 : 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 5 : if( nSrcYSize == -1 )
566 : {
567 2 : nSrcXOff = 0;
568 2 : nSrcYOff = 0;
569 2 : nSrcXSize = poSrcBand->GetXSize();
570 2 : nSrcYSize = poSrcBand->GetYSize();
571 : }
572 :
573 5 : if( nDstYSize == -1 )
574 : {
575 2 : nDstXOff = 0;
576 2 : nDstYOff = 0;
577 2 : nDstXSize = nRasterXSize;
578 2 : nDstYSize = nRasterYSize;
579 : }
580 :
581 : /* -------------------------------------------------------------------- */
582 : /* Create source. */
583 : /* -------------------------------------------------------------------- */
584 5 : VRTSimpleSource* poSimpleSource = new VRTSimpleSource();
585 5 : poSimpleSource->SetSrcMaskBand( poSrcBand );
586 5 : poSimpleSource->SetSrcWindow( 0, 0, poSrcBand->GetXSize(), poSrcBand->GetYSize() );
587 5 : poSimpleSource->SetDstWindow( 0, 0, nRasterXSize, nRasterYSize );
588 :
589 : /* -------------------------------------------------------------------- */
590 : /* Default source and dest rectangles. */
591 : /* -------------------------------------------------------------------- */
592 10 : if ( nSrcXOff == nDstXOff && nSrcYOff == nDstYOff &&
593 : nSrcXSize == nDstXSize && nSrcYSize == nRasterYSize )
594 5 : bEqualAreas = TRUE;
595 :
596 : /* -------------------------------------------------------------------- */
597 : /* If we can get the associated GDALDataset, add a reference to it.*/
598 : /* -------------------------------------------------------------------- */
599 5 : if( poSrcBand->GetDataset() != NULL )
600 5 : poSrcBand->GetDataset()->Reference();
601 :
602 : /* -------------------------------------------------------------------- */
603 : /* add to list. */
604 : /* -------------------------------------------------------------------- */
605 5 : return AddSource( poSimpleSource );
606 : }
607 :
608 : /************************************************************************/
609 : /* VRTAddSimpleSource() */
610 : /************************************************************************/
611 :
612 : /**
613 : * @see VRTSourcedRasterBand::AddSimpleSource().
614 : */
615 :
616 40 : 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 40 : 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 40 : pszResampling, dfNoDataValue );
634 : }
635 :
636 : /************************************************************************/
637 : /* AddComplexSource() */
638 : /************************************************************************/
639 :
640 24 : 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 24 : 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 24 : 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 24 : poSource = new VRTComplexSource();
676 :
677 24 : poSource->SetSrcBand( poSrcBand );
678 24 : poSource->SetSrcWindow( nSrcXOff, nSrcYOff, nSrcXSize, nSrcYSize );
679 24 : poSource->SetDstWindow( nDstXOff, nDstYOff, nDstXSize, nDstYSize );
680 :
681 : /* -------------------------------------------------------------------- */
682 : /* Set complex parameters. */
683 : /* -------------------------------------------------------------------- */
684 24 : if( dfNoDataValue != VRT_NODATA_UNSET )
685 8 : poSource->SetNoDataValue( dfNoDataValue );
686 :
687 24 : if( dfScaleOff != 0.0 || dfScaleRatio != 1.0 )
688 : {
689 1 : poSource->bDoScaling = TRUE;
690 1 : poSource->dfScaleOff = dfScaleOff;
691 1 : poSource->dfScaleRatio = dfScaleRatio;
692 :
693 : }
694 :
695 24 : poSource->nColorTableComponent = nColorTableComponent;
696 :
697 : /* -------------------------------------------------------------------- */
698 : /* If we can get the associated GDALDataset, add a reference to it.*/
699 : /* -------------------------------------------------------------------- */
700 24 : if( poSrcBand->GetDataset() != NULL )
701 24 : poSrcBand->GetDataset()->Reference();
702 :
703 : /* -------------------------------------------------------------------- */
704 : /* add to list. */
705 : /* -------------------------------------------------------------------- */
706 24 : return AddSource( poSource );
707 : }
708 :
709 : /************************************************************************/
710 : /* VRTAddComplexSource() */
711 : /************************************************************************/
712 :
713 : /**
714 : * @see VRTSourcedRasterBand::AddComplexSource().
715 : */
716 :
717 8 : 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 8 : 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 8 : 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 226 : const char *VRTSourcedRasterBand::GetMetadataItem( const char * pszName,
787 : const char * pszDomain )
788 :
789 : {
790 : /* ==================================================================== */
791 : /* LocationInfo handling. */
792 : /* ==================================================================== */
793 226 : 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 1 : if( EQUALN(pszName,"Pixel_",6) )
803 : {
804 1 : 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 1 : 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 1 : char **papszFileList = NULL;
846 1 : int nListMaxSize = 0, nListSize = 0;
847 : CPLHashSet* hSetFiles = CPLHashSetNew(CPLHashSetHashStr,
848 : CPLHashSetEqualStr,
849 1 : NULL);
850 :
851 2 : for( int iSource = 0; iSource < nSources; iSource++ )
852 : {
853 : int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
854 : int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
855 :
856 1 : if (!papoSources[iSource]->IsSimpleSource())
857 0 : continue;
858 :
859 1 : VRTSimpleSource *poSrc = (VRTSimpleSource *) papoSources[iSource];
860 :
861 1 : 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 1 : hSetFiles );
870 : }
871 :
872 : /* -------------------------------------------------------------------- */
873 : /* Format into XML. */
874 : /* -------------------------------------------------------------------- */
875 : int i;
876 :
877 1 : osLastLocationInfo = "<LocationInfo>";
878 2 : for( i = 0; i < nListSize; i++ )
879 : {
880 1 : osLastLocationInfo += "<File>";
881 1 : char* pszXMLEscaped = CPLEscapeString(papszFileList[i], -1, CPLES_XML);
882 1 : osLastLocationInfo += pszXMLEscaped;
883 1 : CPLFree(pszXMLEscaped);
884 1 : osLastLocationInfo += "</File>";
885 : }
886 1 : osLastLocationInfo += "</LocationInfo>";
887 :
888 1 : CSLDestroy( papszFileList );
889 1 : CPLHashSetDestroy( hSetFiles );
890 :
891 1 : return osLastLocationInfo.c_str();
892 : }
893 :
894 : /* ==================================================================== */
895 : /* Other domains. */
896 : /* ==================================================================== */
897 : else
898 225 : return GDALRasterBand::GetMetadataItem( pszName, pszDomain );
899 : }
900 :
901 : /************************************************************************/
902 : /* GetMetadata() */
903 : /************************************************************************/
904 :
905 392 : char **VRTSourcedRasterBand::GetMetadata( const char *pszDomain )
906 :
907 : {
908 : /* ==================================================================== */
909 : /* vrt_sources domain handling. */
910 : /* ==================================================================== */
911 392 : 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 392 : return GDALRasterBand::GetMetadata( pszDomain );
944 : }
945 :
946 : /************************************************************************/
947 : /* SetMetadataItem() */
948 : /************************************************************************/
949 :
950 16 : 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 16 : pszName, pszValue, pszDomain );
957 :
958 16 : if( pszDomain != NULL
959 : && EQUAL(pszDomain,"new_vrt_sources") )
960 : {
961 1 : VRTDriver *poDriver = (VRTDriver *) GDALGetDriverByName( "VRT" );
962 :
963 1 : CPLXMLNode *psTree = CPLParseXMLString( pszValue );
964 : VRTSource *poSource;
965 :
966 1 : if( psTree == NULL )
967 0 : return CE_Failure;
968 :
969 1 : poSource = poDriver->ParseSource( psTree, NULL );
970 1 : CPLDestroyXMLNode( psTree );
971 :
972 1 : if( poSource != NULL )
973 1 : return AddSource( poSource );
974 : else
975 0 : return CE_Failure;
976 : }
977 15 : else if( pszDomain != NULL
978 : && EQUAL(pszDomain,"vrt_sources") )
979 : {
980 : int iSource;
981 1 : 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 1 : VRTDriver *poDriver = (VRTDriver *) GDALGetDriverByName( "VRT" );
992 :
993 1 : CPLXMLNode *psTree = CPLParseXMLString( pszValue );
994 : VRTSource *poSource;
995 :
996 1 : if( psTree == NULL )
997 0 : return CE_Failure;
998 :
999 1 : poSource = poDriver->ParseSource( psTree, NULL );
1000 1 : CPLDestroyXMLNode( psTree );
1001 :
1002 1 : if( poSource != NULL )
1003 : {
1004 1 : delete papoSources[iSource];
1005 1 : papoSources[iSource] = poSource;
1006 1 : ((VRTDataset *)poDS)->SetNeedsFlush();
1007 1 : return CE_None;
1008 : }
1009 : else
1010 0 : return CE_Failure;
1011 : }
1012 : else
1013 14 : return VRTRasterBand::SetMetadataItem( pszName, pszValue, pszDomain );
1014 : }
1015 :
1016 : /************************************************************************/
1017 : /* SetMetadata() */
1018 : /************************************************************************/
1019 :
1020 168 : CPLErr VRTSourcedRasterBand::SetMetadata( char **papszNewMD, const char *pszDomain )
1021 :
1022 : {
1023 168 : if( pszDomain != NULL
1024 : && (EQUAL(pszDomain,"new_vrt_sources")
1025 : || EQUAL(pszDomain,"vrt_sources")) )
1026 : {
1027 4 : VRTDriver *poDriver = (VRTDriver *) GDALGetDriverByName( "VRT" );
1028 : CPLErr eErr;
1029 : int i;
1030 :
1031 4 : if( EQUAL(pszDomain,"vrt_sources") )
1032 : {
1033 4 : for( int i = 0; i < nSources; i++ )
1034 0 : delete papoSources[i];
1035 4 : CPLFree( papoSources );
1036 4 : papoSources = NULL;
1037 4 : nSources = 0;
1038 : }
1039 :
1040 16 : for( i = 0; i < CSLCount(papszNewMD); i++ )
1041 : {
1042 4 : const char *pszXML = CPLParseNameValue( papszNewMD[i], NULL );
1043 4 : CPLXMLNode *psTree = CPLParseXMLString( pszXML );
1044 : VRTSource *poSource;
1045 :
1046 4 : if( psTree == NULL )
1047 0 : return CE_Failure;
1048 :
1049 4 : poSource = poDriver->ParseSource( psTree, NULL );
1050 4 : CPLDestroyXMLNode( psTree );
1051 :
1052 4 : if( poSource != NULL )
1053 : {
1054 4 : eErr = AddSource( poSource );
1055 4 : if( eErr != CE_None )
1056 0 : return eErr;
1057 : }
1058 : else
1059 0 : return CE_Failure;
1060 : }
1061 :
1062 4 : return CE_None;
1063 : }
1064 : else
1065 164 : return VRTRasterBand::SetMetadata( papszNewMD, pszDomain );
1066 : }
1067 :
1068 : /************************************************************************/
1069 : /* GetFileList() */
1070 : /************************************************************************/
1071 :
1072 4 : void VRTSourcedRasterBand::GetFileList(char*** ppapszFileList, int *pnSize,
1073 : int *pnMaxSize, CPLHashSet* hSetFiles)
1074 : {
1075 8 : for( int i = 0; i < nSources; i++ )
1076 : {
1077 12 : papoSources[i]->GetFileList(ppapszFileList, pnSize,
1078 16 : pnMaxSize, hSetFiles);
1079 : }
1080 :
1081 : VRTRasterBand::GetFileList( ppapszFileList, pnSize,
1082 4 : pnMaxSize, hSetFiles);
1083 4 : }
1084 :
1085 : /************************************************************************/
1086 : /* CloseDependentDatasets() */
1087 : /************************************************************************/
1088 :
1089 648 : int VRTSourcedRasterBand::CloseDependentDatasets()
1090 : {
1091 648 : if (nSources == 0)
1092 112 : return FALSE;
1093 :
1094 1165 : for( int i = 0; i < nSources; i++ )
1095 629 : delete papoSources[i];
1096 :
1097 536 : CPLFree( papoSources );
1098 536 : papoSources = NULL;
1099 536 : nSources = 0;
1100 :
1101 536 : return TRUE;
1102 : }
|