1 : /******************************************************************************
2 : * $Id: vrtrasterband.cpp 22761 2011-07-21 18:53:58Z rouault $
3 : *
4 : * Project: Virtual GDAL Datasets
5 : * Purpose: Implementation of VRTRasterBand
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: vrtrasterband.cpp 22761 2011-07-21 18:53:58Z rouault $");
35 :
36 : /************************************************************************/
37 : /* ==================================================================== */
38 : /* VRTRasterBand */
39 : /* ==================================================================== */
40 : /************************************************************************/
41 :
42 : /************************************************************************/
43 : /* VRTRasterBand() */
44 : /************************************************************************/
45 :
46 2507 : VRTRasterBand::VRTRasterBand()
47 :
48 : {
49 2507 : Initialize( 0, 0 );
50 2507 : }
51 :
52 : /************************************************************************/
53 : /* Initialize() */
54 : /************************************************************************/
55 :
56 5014 : void VRTRasterBand::Initialize( int nXSize, int nYSize )
57 :
58 : {
59 5014 : poDS = NULL;
60 5014 : nBand = 0;
61 5014 : eAccess = GA_ReadOnly;
62 5014 : eDataType = GDT_Byte;
63 :
64 5014 : nRasterXSize = nXSize;
65 5014 : nRasterYSize = nYSize;
66 :
67 5014 : nBlockXSize = MIN(128,nXSize);
68 5014 : nBlockYSize = MIN(128,nYSize);
69 :
70 5014 : bIsMaskBand = FALSE;
71 5014 : bNoDataValueSet = FALSE;
72 5014 : bHideNoDataValue = FALSE;
73 5014 : dfNoDataValue = -10000.0;
74 5014 : poColorTable = NULL;
75 5014 : eColorInterp = GCI_Undefined;
76 :
77 5014 : pszUnitType = NULL;
78 5014 : papszCategoryNames = NULL;
79 5014 : dfOffset = 0.0;
80 5014 : dfScale = 1.0;
81 :
82 5014 : psSavedHistograms = NULL;
83 :
84 5014 : poMaskBand = NULL;
85 5014 : }
86 :
87 : /************************************************************************/
88 : /* ~VRTRasterBand() */
89 : /************************************************************************/
90 :
91 2507 : VRTRasterBand::~VRTRasterBand()
92 :
93 : {
94 2507 : CPLFree( pszUnitType );
95 :
96 2507 : if( poColorTable != NULL )
97 12 : delete poColorTable;
98 :
99 2507 : CSLDestroy( papszCategoryNames );
100 2507 : if( psSavedHistograms != NULL )
101 0 : CPLDestroyXMLNode( psSavedHistograms );
102 :
103 2507 : delete poMaskBand;
104 2507 : }
105 :
106 : /************************************************************************/
107 : /* CopyCommonInfoFrom() */
108 : /* */
109 : /* Copy common metadata, pixel descriptions, and color */
110 : /* interpretation from the provided source band. */
111 : /************************************************************************/
112 :
113 129 : CPLErr VRTRasterBand::CopyCommonInfoFrom( GDALRasterBand * poSrcBand )
114 :
115 : {
116 : int bSuccess;
117 : double dfNoData;
118 :
119 129 : SetMetadata( poSrcBand->GetMetadata() );
120 129 : SetColorTable( poSrcBand->GetColorTable() );
121 129 : SetColorInterpretation(poSrcBand->GetColorInterpretation());
122 129 : if( strlen(poSrcBand->GetDescription()) > 0 )
123 1 : SetDescription( poSrcBand->GetDescription() );
124 129 : dfNoData = poSrcBand->GetNoDataValue( &bSuccess );
125 129 : if( bSuccess )
126 0 : SetNoDataValue( dfNoData );
127 :
128 129 : SetOffset( poSrcBand->GetOffset() );
129 129 : SetScale( poSrcBand->GetScale() );
130 129 : SetCategoryNames( poSrcBand->GetCategoryNames() );
131 129 : if( !EQUAL(poSrcBand->GetUnitType(),"") )
132 1 : SetUnitType( poSrcBand->GetUnitType() );
133 :
134 129 : return CE_None;
135 : }
136 :
137 : /************************************************************************/
138 : /* SetMetadata() */
139 : /************************************************************************/
140 :
141 201 : CPLErr VRTRasterBand::SetMetadata( char **papszMetadata,
142 : const char *pszDomain )
143 :
144 : {
145 201 : ((VRTDataset *) poDS)->SetNeedsFlush();
146 :
147 201 : return GDALRasterBand::SetMetadata( papszMetadata, pszDomain );
148 : }
149 :
150 : /************************************************************************/
151 : /* SetMetadataItem() */
152 : /************************************************************************/
153 :
154 18 : CPLErr VRTRasterBand::SetMetadataItem( const char *pszName,
155 : const char *pszValue,
156 : const char *pszDomain )
157 :
158 : {
159 18 : ((VRTDataset *) poDS)->SetNeedsFlush();
160 :
161 18 : if( EQUAL(pszName,"HideNoDataValue") )
162 : {
163 0 : bHideNoDataValue = CSLTestBoolean( pszValue );
164 0 : return CE_None;
165 : }
166 : else
167 18 : return GDALRasterBand::SetMetadataItem( pszName, pszValue, pszDomain );
168 : }
169 :
170 : /************************************************************************/
171 : /* GetUnitType() */
172 : /************************************************************************/
173 :
174 277 : const char *VRTRasterBand::GetUnitType()
175 :
176 : {
177 277 : if( pszUnitType == NULL )
178 273 : return "";
179 : else
180 4 : return pszUnitType;
181 : }
182 :
183 : /************************************************************************/
184 : /* SetUnitType() */
185 : /************************************************************************/
186 :
187 563 : CPLErr VRTRasterBand::SetUnitType( const char *pszNewValue )
188 :
189 : {
190 563 : ((VRTDataset *) poDS)->SetNeedsFlush();
191 :
192 563 : CPLFree( pszUnitType );
193 :
194 563 : if( pszNewValue == NULL )
195 560 : pszUnitType = NULL;
196 : else
197 3 : pszUnitType = CPLStrdup(pszNewValue);
198 :
199 563 : return CE_None;
200 : }
201 :
202 : /************************************************************************/
203 : /* GetOffset() */
204 : /************************************************************************/
205 :
206 287 : double VRTRasterBand::GetOffset( int *pbSuccess )
207 :
208 : {
209 287 : if( pbSuccess != NULL )
210 160 : *pbSuccess = TRUE;
211 :
212 287 : return dfOffset;
213 : }
214 :
215 : /************************************************************************/
216 : /* SetOffset() */
217 : /************************************************************************/
218 :
219 754 : CPLErr VRTRasterBand::SetOffset( double dfNewOffset )
220 :
221 : {
222 754 : ((VRTDataset *) poDS)->SetNeedsFlush();
223 :
224 754 : dfOffset = dfNewOffset;
225 754 : return CE_None;
226 : }
227 :
228 : /************************************************************************/
229 : /* GetScale() */
230 : /************************************************************************/
231 :
232 287 : double VRTRasterBand::GetScale( int *pbSuccess )
233 :
234 : {
235 287 : if( pbSuccess != NULL )
236 160 : *pbSuccess = TRUE;
237 :
238 287 : return dfScale;
239 : }
240 :
241 : /************************************************************************/
242 : /* SetScale() */
243 : /************************************************************************/
244 :
245 754 : CPLErr VRTRasterBand::SetScale( double dfNewScale )
246 :
247 : {
248 754 : ((VRTDataset *) poDS)->SetNeedsFlush();
249 :
250 754 : dfScale = dfNewScale;
251 754 : return CE_None;
252 : }
253 :
254 : /************************************************************************/
255 : /* GetCategoryNames() */
256 : /************************************************************************/
257 :
258 278 : char **VRTRasterBand::GetCategoryNames()
259 :
260 : {
261 278 : return papszCategoryNames;
262 : }
263 :
264 : /************************************************************************/
265 : /* SetCategoryNames() */
266 : /************************************************************************/
267 :
268 193 : CPLErr VRTRasterBand::SetCategoryNames( char ** papszNewNames )
269 :
270 : {
271 193 : ((VRTDataset *) poDS)->SetNeedsFlush();
272 :
273 193 : CSLDestroy( papszCategoryNames );
274 193 : papszCategoryNames = CSLDuplicate( papszNewNames );
275 :
276 193 : return CE_None;
277 : }
278 :
279 : /************************************************************************/
280 : /* XMLInit() */
281 : /************************************************************************/
282 :
283 561 : CPLErr VRTRasterBand::XMLInit( CPLXMLNode * psTree,
284 : const char *pszVRTPath )
285 :
286 : {
287 : /* -------------------------------------------------------------------- */
288 : /* Validate a bit. */
289 : /* -------------------------------------------------------------------- */
290 561 : if( psTree == NULL || psTree->eType != CXT_Element
291 : || !EQUAL(psTree->pszValue,"VRTRasterBand") )
292 : {
293 : CPLError( CE_Failure, CPLE_AppDefined,
294 0 : "Invalid node passed to VRTRasterBand::XMLInit()." );
295 0 : return CE_Failure;
296 : }
297 :
298 : /* -------------------------------------------------------------------- */
299 : /* Set the band if provided as an attribute. */
300 : /* -------------------------------------------------------------------- */
301 561 : const char* pszBand = CPLGetXMLValue( psTree, "band", NULL);
302 561 : if( pszBand != NULL )
303 : {
304 550 : nBand = atoi(pszBand);
305 : }
306 :
307 : /* -------------------------------------------------------------------- */
308 : /* Set the band if provided as an attribute. */
309 : /* -------------------------------------------------------------------- */
310 561 : const char *pszDataType = CPLGetXMLValue( psTree, "dataType", NULL);
311 561 : if( pszDataType != NULL )
312 : {
313 561 : eDataType = GDALGetDataTypeByName(pszDataType);
314 : }
315 :
316 : /* -------------------------------------------------------------------- */
317 : /* Apply any band level metadata. */
318 : /* -------------------------------------------------------------------- */
319 561 : oMDMD.XMLInit( psTree, TRUE );
320 :
321 : /* -------------------------------------------------------------------- */
322 : /* Collect various other items of metadata. */
323 : /* -------------------------------------------------------------------- */
324 561 : SetDescription( CPLGetXMLValue( psTree, "Description", "" ) );
325 :
326 561 : if( CPLGetXMLValue( psTree, "NoDataValue", NULL ) != NULL )
327 48 : SetNoDataValue( CPLAtofM(CPLGetXMLValue( psTree, "NoDataValue", "0" )) );
328 :
329 561 : if( CPLGetXMLValue( psTree, "HideNoDataValue", NULL ) != NULL )
330 0 : bHideNoDataValue = CSLTestBoolean( CPLGetXMLValue( psTree, "HideNoDataValue", "0" ) );
331 :
332 561 : SetUnitType( CPLGetXMLValue( psTree, "UnitType", NULL ) );
333 :
334 561 : SetOffset( atof(CPLGetXMLValue( psTree, "Offset", "0.0" )) );
335 561 : SetScale( atof(CPLGetXMLValue( psTree, "Scale", "1.0" )) );
336 :
337 561 : if( CPLGetXMLValue( psTree, "ColorInterp", NULL ) != NULL )
338 : {
339 303 : const char *pszInterp = CPLGetXMLValue( psTree, "ColorInterp", NULL );
340 303 : SetColorInterpretation(GDALGetColorInterpretationByName(pszInterp));
341 : }
342 :
343 : /* -------------------------------------------------------------------- */
344 : /* Category names. */
345 : /* -------------------------------------------------------------------- */
346 561 : if( CPLGetXMLNode( psTree, "CategoryNames" ) != NULL )
347 : {
348 : CPLXMLNode *psEntry;
349 :
350 1 : CSLDestroy( papszCategoryNames );
351 1 : papszCategoryNames = NULL;
352 :
353 1 : CPLStringList oCategoryNames;
354 :
355 3 : for( psEntry = CPLGetXMLNode( psTree, "CategoryNames" )->psChild;
356 : psEntry != NULL; psEntry = psEntry->psNext )
357 : {
358 2 : if( psEntry->eType != CXT_Element
359 : || !EQUAL(psEntry->pszValue,"Category")
360 : || (psEntry->psChild != NULL && psEntry->psChild->eType != CXT_Text) )
361 0 : continue;
362 :
363 : oCategoryNames.AddString(
364 2 : (psEntry->psChild) ? psEntry->psChild->pszValue : "");
365 : }
366 :
367 1 : papszCategoryNames = oCategoryNames.StealList();
368 : }
369 :
370 : /* -------------------------------------------------------------------- */
371 : /* Collect a color table. */
372 : /* -------------------------------------------------------------------- */
373 561 : if( CPLGetXMLNode( psTree, "ColorTable" ) != NULL )
374 : {
375 : CPLXMLNode *psEntry;
376 4 : GDALColorTable oTable;
377 4 : int iEntry = 0;
378 :
379 520 : for( psEntry = CPLGetXMLNode( psTree, "ColorTable" )->psChild;
380 : psEntry != NULL; psEntry = psEntry->psNext )
381 : {
382 : GDALColorEntry sCEntry;
383 :
384 516 : sCEntry.c1 = (short) atoi(CPLGetXMLValue( psEntry, "c1", "0" ));
385 516 : sCEntry.c2 = (short) atoi(CPLGetXMLValue( psEntry, "c2", "0" ));
386 516 : sCEntry.c3 = (short) atoi(CPLGetXMLValue( psEntry, "c3", "0" ));
387 516 : sCEntry.c4 = (short) atoi(CPLGetXMLValue( psEntry, "c4", "255" ));
388 :
389 516 : oTable.SetColorEntry( iEntry++, &sCEntry );
390 : }
391 :
392 4 : SetColorTable( &oTable );
393 : }
394 :
395 : /* -------------------------------------------------------------------- */
396 : /* Histograms */
397 : /* -------------------------------------------------------------------- */
398 561 : CPLXMLNode *psHist = CPLGetXMLNode( psTree, "Histograms" );
399 561 : if( psHist != NULL )
400 : {
401 0 : CPLXMLNode *psNext = psHist->psNext;
402 0 : psHist->psNext = NULL;
403 :
404 0 : psSavedHistograms = CPLCloneXMLTree( psHist );
405 0 : psHist->psNext = psNext;
406 : }
407 :
408 : /* ==================================================================== */
409 : /* Overviews */
410 : /* ==================================================================== */
411 : CPLXMLNode *psNode;
412 :
413 2841 : for( psNode = psTree->psChild; psNode != NULL; psNode = psNode->psNext )
414 : {
415 2280 : if( psNode->eType != CXT_Element
416 : || !EQUAL(psNode->pszValue,"Overview") )
417 2271 : continue;
418 :
419 : /* -------------------------------------------------------------------- */
420 : /* Prepare filename. */
421 : /* -------------------------------------------------------------------- */
422 9 : char *pszSrcDSName = NULL;
423 9 : CPLXMLNode* psFileNameNode=CPLGetXMLNode(psNode,"SourceFilename");
424 : const char *pszFilename =
425 9 : psFileNameNode ? CPLGetXMLValue(psFileNameNode,NULL, NULL) : NULL;
426 :
427 9 : if( pszFilename == NULL )
428 : {
429 : CPLError( CE_Warning, CPLE_AppDefined,
430 0 : "Missing <SourceFilename> element in Overview." );
431 0 : return CE_Failure;
432 : }
433 :
434 9 : if (EQUALN(pszFilename, "MEM:::", 6) && pszVRTPath != NULL &&
435 : !CSLTestBoolean(CPLGetConfigOption("VRT_ALLOW_MEM_DRIVER", "NO")))
436 : {
437 : CPLError( CE_Failure, CPLE_AppDefined,
438 : "<SourceFilename> points to a MEM dataset, which is rather suspect! "
439 0 : "If you know what you are doing, define the VRT_ALLOW_MEM_DRIVER configuration option to YES" );
440 0 : return CE_Failure;
441 : }
442 :
443 9 : if( pszVRTPath != NULL
444 : && atoi(CPLGetXMLValue( psFileNameNode, "relativetoVRT", "0")) )
445 : {
446 : pszSrcDSName = CPLStrdup(
447 0 : CPLProjectRelativeFilename( pszVRTPath, pszFilename ) );
448 : }
449 : else
450 9 : pszSrcDSName = CPLStrdup( pszFilename );
451 :
452 : /* -------------------------------------------------------------------- */
453 : /* Get the raster band. */
454 : /* -------------------------------------------------------------------- */
455 9 : int nSrcBand = atoi(CPLGetXMLValue(psNode,"SourceBand","1"));
456 :
457 9 : apoOverviews.resize( apoOverviews.size() + 1 );
458 18 : apoOverviews[apoOverviews.size()-1].osFilename = pszSrcDSName;
459 9 : apoOverviews[apoOverviews.size()-1].nBand = nSrcBand;
460 :
461 9 : CPLFree( pszSrcDSName );
462 : }
463 :
464 : /* ==================================================================== */
465 : /* Mask band (specific to that raster band) */
466 : /* ==================================================================== */
467 561 : CPLXMLNode* psMaskBandNode = CPLGetXMLNode(psTree, "MaskBand");
468 561 : if (psMaskBandNode)
469 1 : psNode = psMaskBandNode->psChild;
470 : else
471 560 : psNode = NULL;
472 1122 : for( ; psNode != NULL; psNode = psNode->psNext )
473 : {
474 1 : if( psNode->eType != CXT_Element
475 : || !EQUAL(psNode->pszValue,"VRTRasterBand") )
476 0 : continue;
477 :
478 1 : if( ((VRTDataset*)poDS)->poMaskBand != NULL)
479 : {
480 : CPLError( CE_Warning, CPLE_AppDefined,
481 0 : "Illegal mask band at raster band level when a dataset mask band already exists." );
482 0 : break;
483 : }
484 :
485 : const char *pszSubclass = CPLGetXMLValue( psNode, "subclass",
486 1 : "VRTSourcedRasterBand" );
487 1 : VRTRasterBand *poBand = NULL;
488 :
489 1 : if( EQUAL(pszSubclass,"VRTSourcedRasterBand") )
490 1 : poBand = new VRTSourcedRasterBand( GetDataset(), 0 );
491 0 : else if( EQUAL(pszSubclass, "VRTDerivedRasterBand") )
492 0 : poBand = new VRTDerivedRasterBand( GetDataset(), 0 );
493 0 : else if( EQUAL(pszSubclass, "VRTRawRasterBand") )
494 0 : poBand = new VRTRawRasterBand( GetDataset(), 0 );
495 0 : else if( EQUAL(pszSubclass, "VRTWarpedRasterBand") )
496 0 : poBand = new VRTWarpedRasterBand( GetDataset(), 0 );
497 : else
498 : {
499 : CPLError( CE_Failure, CPLE_AppDefined,
500 : "VRTRasterBand of unrecognised subclass '%s'.",
501 0 : pszSubclass );
502 0 : break;
503 : }
504 :
505 :
506 1 : if( poBand->XMLInit( psNode, pszVRTPath ) == CE_None )
507 : {
508 1 : SetMaskBand(poBand);
509 : }
510 :
511 1 : break;
512 : }
513 :
514 561 : return CE_None;
515 : }
516 :
517 : /************************************************************************/
518 : /* SerializeToXML() */
519 : /************************************************************************/
520 :
521 243 : CPLXMLNode *VRTRasterBand::SerializeToXML( const char *pszVRTPath )
522 :
523 : {
524 : CPLXMLNode *psTree;
525 :
526 243 : psTree = CPLCreateXMLNode( NULL, CXT_Element, "VRTRasterBand" );
527 :
528 : /* -------------------------------------------------------------------- */
529 : /* Various kinds of metadata. */
530 : /* -------------------------------------------------------------------- */
531 : CPLXMLNode *psMD;
532 :
533 : CPLSetXMLValue( psTree, "#dataType",
534 243 : GDALGetDataTypeName( GetRasterDataType() ) );
535 :
536 243 : if( nBand > 0 )
537 237 : CPLSetXMLValue( psTree, "#band", CPLSPrintf( "%d", GetBand() ) );
538 :
539 243 : psMD = oMDMD.Serialize();
540 243 : if( psMD != NULL )
541 141 : CPLAddXMLChild( psTree, psMD );
542 :
543 243 : if( strlen(GetDescription()) > 0 )
544 3 : CPLSetXMLValue( psTree, "Description", GetDescription() );
545 :
546 243 : if( bNoDataValueSet )
547 : {
548 4 : if (CPLIsNan(dfNoDataValue))
549 0 : CPLSetXMLValue( psTree, "NoDataValue", "nan");
550 : else
551 : CPLSetXMLValue( psTree, "NoDataValue",
552 4 : CPLSPrintf( "%.14E", dfNoDataValue ) );
553 : }
554 :
555 243 : if( bHideNoDataValue )
556 : CPLSetXMLValue( psTree, "HideNoDataValue",
557 0 : CPLSPrintf( "%d", bHideNoDataValue ) );
558 :
559 243 : if( pszUnitType != NULL )
560 1 : CPLSetXMLValue( psTree, "UnitType", pszUnitType );
561 :
562 243 : if( dfOffset != 0.0 )
563 : CPLSetXMLValue( psTree, "Offset",
564 1 : CPLSPrintf( "%.16g", dfOffset ) );
565 :
566 243 : if( dfScale != 1.0 )
567 : CPLSetXMLValue( psTree, "Scale",
568 1 : CPLSPrintf( "%.16g", dfScale ) );
569 :
570 243 : if( eColorInterp != GCI_Undefined )
571 : CPLSetXMLValue( psTree, "ColorInterp",
572 149 : GDALGetColorInterpretationName( eColorInterp ) );
573 :
574 : /* -------------------------------------------------------------------- */
575 : /* Category names. */
576 : /* -------------------------------------------------------------------- */
577 243 : if( papszCategoryNames != NULL )
578 : {
579 : CPLXMLNode *psCT_XML = CPLCreateXMLNode( psTree, CXT_Element,
580 1 : "CategoryNames" );
581 1 : CPLXMLNode* psLastChild = NULL;
582 :
583 3 : for( int iEntry=0; papszCategoryNames[iEntry] != NULL; iEntry++ )
584 : {
585 : CPLXMLNode *psNode = CPLCreateXMLElementAndValue( NULL, "Category",
586 2 : papszCategoryNames[iEntry] );
587 2 : if( psLastChild == NULL )
588 1 : psCT_XML->psChild = psNode;
589 : else
590 1 : psLastChild->psNext = psNode;
591 2 : psLastChild = psNode;
592 : }
593 : }
594 :
595 : /* -------------------------------------------------------------------- */
596 : /* Histograms. */
597 : /* -------------------------------------------------------------------- */
598 243 : if( psSavedHistograms != NULL )
599 0 : CPLAddXMLChild( psTree, CPLCloneXMLTree( psSavedHistograms ) );
600 :
601 : /* -------------------------------------------------------------------- */
602 : /* Color Table. */
603 : /* -------------------------------------------------------------------- */
604 243 : if( poColorTable != NULL )
605 : {
606 : CPLXMLNode *psCT_XML = CPLCreateXMLNode( psTree, CXT_Element,
607 3 : "ColorTable" );
608 3 : CPLXMLNode* psLastChild = NULL;
609 :
610 263 : for( int iEntry=0; iEntry < poColorTable->GetColorEntryCount();
611 : iEntry++ )
612 : {
613 : GDALColorEntry sEntry;
614 : CPLXMLNode *psEntry_XML = CPLCreateXMLNode( NULL, CXT_Element,
615 260 : "Entry" );
616 260 : if( psLastChild == NULL )
617 3 : psCT_XML->psChild = psEntry_XML;
618 : else
619 257 : psLastChild->psNext = psEntry_XML;
620 260 : psLastChild = psEntry_XML;
621 :
622 260 : poColorTable->GetColorEntryAsRGB( iEntry, &sEntry );
623 :
624 260 : CPLSetXMLValue( psEntry_XML, "#c1", CPLSPrintf("%d",sEntry.c1) );
625 260 : CPLSetXMLValue( psEntry_XML, "#c2", CPLSPrintf("%d",sEntry.c2) );
626 260 : CPLSetXMLValue( psEntry_XML, "#c3", CPLSPrintf("%d",sEntry.c3) );
627 260 : CPLSetXMLValue( psEntry_XML, "#c4", CPLSPrintf("%d",sEntry.c4) );
628 : }
629 : }
630 :
631 : /* ==================================================================== */
632 : /* Overviews */
633 : /* ==================================================================== */
634 :
635 244 : for( int iOvr = 0; iOvr < (int)apoOverviews.size(); iOvr ++ )
636 : {
637 : CPLXMLNode *psOVR_XML = CPLCreateXMLNode( psTree, CXT_Element,
638 1 : "Overview" );
639 :
640 : int bRelativeToVRT;
641 : const char *pszRelativePath;
642 : VSIStatBufL sStat;
643 :
644 1 : if( VSIStatExL( apoOverviews[iOvr].osFilename, &sStat, VSI_STAT_EXISTS_FLAG ) != 0 )
645 : {
646 0 : pszRelativePath = apoOverviews[iOvr].osFilename;
647 0 : bRelativeToVRT = FALSE;
648 : }
649 : else
650 : {
651 : pszRelativePath =
652 : CPLExtractRelativePath( pszVRTPath, apoOverviews[iOvr].osFilename,
653 1 : &bRelativeToVRT );
654 : }
655 :
656 1 : CPLSetXMLValue( psOVR_XML, "SourceFilename", pszRelativePath );
657 :
658 : CPLCreateXMLNode(
659 : CPLCreateXMLNode( CPLGetXMLNode( psOVR_XML, "SourceFilename" ),
660 : CXT_Attribute, "relativeToVRT" ),
661 1 : CXT_Text, bRelativeToVRT ? "1" : "0" );
662 :
663 : CPLSetXMLValue( psOVR_XML, "SourceBand",
664 1 : CPLSPrintf("%d",apoOverviews[iOvr].nBand) );
665 : }
666 :
667 : /* ==================================================================== */
668 : /* Mask band (specific to that raster band) */
669 : /* ==================================================================== */
670 :
671 243 : if( poMaskBand != NULL )
672 : {
673 : CPLXMLNode *psBandTree =
674 0 : poMaskBand->SerializeToXML(pszVRTPath);
675 :
676 0 : if( psBandTree != NULL )
677 : {
678 : CPLXMLNode *psMaskBandElement = CPLCreateXMLNode( psTree, CXT_Element,
679 0 : "MaskBand" );
680 0 : CPLAddXMLChild( psMaskBandElement, psBandTree );
681 : }
682 : }
683 :
684 243 : return psTree;
685 : }
686 :
687 : /************************************************************************/
688 : /* SetNoDataValue() */
689 : /************************************************************************/
690 :
691 60 : CPLErr VRTRasterBand::SetNoDataValue( double dfNewValue )
692 :
693 : {
694 60 : bNoDataValueSet = TRUE;
695 60 : dfNoDataValue = dfNewValue;
696 :
697 60 : ((VRTDataset *)poDS)->SetNeedsFlush();
698 :
699 60 : return CE_None;
700 : }
701 :
702 : /************************************************************************/
703 : /* UnsetNoDataValue() */
704 : /************************************************************************/
705 :
706 0 : CPLErr VRTRasterBand::UnsetNoDataValue()
707 : {
708 0 : bNoDataValueSet = FALSE;
709 0 : dfNoDataValue = -10000.0;
710 :
711 0 : ((VRTDataset *)poDS)->SetNeedsFlush();
712 :
713 0 : return CE_None;
714 : }
715 :
716 : /************************************************************************/
717 : /* GetNoDataValue() */
718 : /************************************************************************/
719 :
720 4780 : double VRTRasterBand::GetNoDataValue( int *pbSuccess )
721 :
722 : {
723 4780 : if( pbSuccess )
724 4739 : *pbSuccess = bNoDataValueSet && !bHideNoDataValue;
725 :
726 4780 : return dfNoDataValue;
727 : }
728 :
729 : /************************************************************************/
730 : /* SetColorTable() */
731 : /************************************************************************/
732 :
733 203 : CPLErr VRTRasterBand::SetColorTable( GDALColorTable *poTableIn )
734 :
735 : {
736 203 : if( poColorTable != NULL )
737 : {
738 0 : delete poColorTable;
739 0 : poColorTable = NULL;
740 : }
741 :
742 203 : if( poTableIn )
743 : {
744 12 : poColorTable = poTableIn->Clone();
745 12 : eColorInterp = GCI_PaletteIndex;
746 : }
747 :
748 203 : ((VRTDataset *)poDS)->SetNeedsFlush();
749 :
750 203 : return CE_None;
751 : }
752 :
753 : /************************************************************************/
754 : /* GetColorTable() */
755 : /************************************************************************/
756 :
757 399 : GDALColorTable *VRTRasterBand::GetColorTable()
758 :
759 : {
760 399 : return poColorTable;
761 : }
762 :
763 : /************************************************************************/
764 : /* SetColorInterpretation() */
765 : /************************************************************************/
766 :
767 572 : CPLErr VRTRasterBand::SetColorInterpretation( GDALColorInterp eInterpIn )
768 :
769 : {
770 572 : ((VRTDataset *)poDS)->SetNeedsFlush();
771 :
772 572 : eColorInterp = eInterpIn;
773 :
774 572 : return CE_None;
775 : }
776 :
777 : /************************************************************************/
778 : /* GetColorInterpretation() */
779 : /************************************************************************/
780 :
781 351 : GDALColorInterp VRTRasterBand::GetColorInterpretation()
782 :
783 : {
784 351 : return eColorInterp;
785 : }
786 :
787 : /************************************************************************/
788 : /* GetHistogram() */
789 : /************************************************************************/
790 :
791 0 : CPLErr VRTRasterBand::GetHistogram( double dfMin, double dfMax,
792 : int nBuckets, int * panHistogram,
793 : int bIncludeOutOfRange, int bApproxOK,
794 : GDALProgressFunc pfnProgress,
795 : void *pProgressData )
796 :
797 : {
798 : /* -------------------------------------------------------------------- */
799 : /* Check if we have a matching histogram. */
800 : /* -------------------------------------------------------------------- */
801 : CPLXMLNode *psHistItem;
802 :
803 : psHistItem = PamFindMatchingHistogram( psSavedHistograms,
804 : dfMin, dfMax, nBuckets,
805 0 : bIncludeOutOfRange, bApproxOK );
806 0 : if( psHistItem != NULL )
807 : {
808 0 : int *panTempHist = NULL;
809 :
810 0 : if( PamParseHistogram( psHistItem, &dfMin, &dfMax, &nBuckets,
811 : &panTempHist,
812 : &bIncludeOutOfRange, &bApproxOK ) )
813 : {
814 0 : memcpy( panHistogram, panTempHist, sizeof(int) * nBuckets );
815 0 : CPLFree( panTempHist );
816 0 : return CE_None;
817 : }
818 : }
819 :
820 : /* -------------------------------------------------------------------- */
821 : /* We don't have an existing histogram matching the request, so */
822 : /* generate one manually. */
823 : /* -------------------------------------------------------------------- */
824 : CPLErr eErr;
825 :
826 : eErr = GDALRasterBand::GetHistogram( dfMin, dfMax,
827 : nBuckets, panHistogram,
828 : bIncludeOutOfRange, bApproxOK,
829 0 : pfnProgress, pProgressData );
830 :
831 : /* -------------------------------------------------------------------- */
832 : /* Save an XML description of this histogram. */
833 : /* -------------------------------------------------------------------- */
834 0 : if( eErr == CE_None )
835 : {
836 : CPLXMLNode *psXMLHist;
837 :
838 : psXMLHist = PamHistogramToXMLTree( dfMin, dfMax, nBuckets,
839 : panHistogram,
840 0 : bIncludeOutOfRange, bApproxOK );
841 0 : if( psXMLHist != NULL )
842 : {
843 0 : ((VRTDataset *) poDS)->SetNeedsFlush();
844 :
845 0 : if( psSavedHistograms == NULL )
846 : psSavedHistograms = CPLCreateXMLNode( NULL, CXT_Element,
847 0 : "Histograms" );
848 :
849 0 : CPLAddXMLChild( psSavedHistograms, psXMLHist );
850 : }
851 : }
852 :
853 0 : return eErr;
854 : }
855 :
856 : /************************************************************************/
857 : /* SetDefaultHistogram() */
858 : /************************************************************************/
859 :
860 0 : CPLErr VRTRasterBand::SetDefaultHistogram( double dfMin, double dfMax,
861 : int nBuckets, int *panHistogram)
862 :
863 : {
864 : CPLXMLNode *psNode;
865 :
866 : /* -------------------------------------------------------------------- */
867 : /* Do we have a matching histogram we should replace? */
868 : /* -------------------------------------------------------------------- */
869 : psNode = PamFindMatchingHistogram( psSavedHistograms,
870 : dfMin, dfMax, nBuckets,
871 0 : TRUE, TRUE );
872 0 : if( psNode != NULL )
873 : {
874 : /* blow this one away */
875 0 : CPLRemoveXMLChild( psSavedHistograms, psNode );
876 0 : CPLDestroyXMLNode( psNode );
877 : }
878 :
879 : /* -------------------------------------------------------------------- */
880 : /* Translate into a histogram XML tree. */
881 : /* -------------------------------------------------------------------- */
882 : CPLXMLNode *psHistItem;
883 :
884 : psHistItem = PamHistogramToXMLTree( dfMin, dfMax, nBuckets,
885 0 : panHistogram, TRUE, FALSE );
886 :
887 : /* -------------------------------------------------------------------- */
888 : /* Insert our new default histogram at the front of the */
889 : /* histogram list so that it will be the default histogram. */
890 : /* -------------------------------------------------------------------- */
891 0 : ((VRTDataset *) poDS)->SetNeedsFlush();
892 :
893 0 : if( psSavedHistograms == NULL )
894 : psSavedHistograms = CPLCreateXMLNode( NULL, CXT_Element,
895 0 : "Histograms" );
896 :
897 0 : psHistItem->psNext = psSavedHistograms->psChild;
898 0 : psSavedHistograms->psChild = psHistItem;
899 :
900 0 : return CE_None;
901 : }
902 :
903 : /************************************************************************/
904 : /* GetDefaultHistogram() */
905 : /************************************************************************/
906 :
907 : CPLErr
908 0 : VRTRasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax,
909 : int *pnBuckets, int **ppanHistogram,
910 : int bForce,
911 : GDALProgressFunc pfnProgress,
912 : void *pProgressData )
913 :
914 : {
915 0 : if( psSavedHistograms != NULL )
916 : {
917 : CPLXMLNode *psXMLHist;
918 :
919 0 : for( psXMLHist = psSavedHistograms->psChild;
920 : psXMLHist != NULL; psXMLHist = psXMLHist->psNext )
921 : {
922 : int bApprox, bIncludeOutOfRange;
923 :
924 0 : if( psXMLHist->eType != CXT_Element
925 : || !EQUAL(psXMLHist->pszValue,"HistItem") )
926 0 : continue;
927 :
928 0 : if( PamParseHistogram( psXMLHist, pdfMin, pdfMax, pnBuckets,
929 : ppanHistogram, &bIncludeOutOfRange,
930 : &bApprox ) )
931 0 : return CE_None;
932 : else
933 0 : return CE_Failure;
934 : }
935 : }
936 :
937 : return GDALRasterBand::GetDefaultHistogram( pdfMin, pdfMax, pnBuckets,
938 : ppanHistogram, bForce,
939 0 : pfnProgress,pProgressData);
940 : }
941 :
942 : /************************************************************************/
943 : /* GetFileList() */
944 : /************************************************************************/
945 :
946 4 : void VRTRasterBand::GetFileList(char*** ppapszFileList, int *pnSize,
947 : int *pnMaxSize, CPLHashSet* hSetFiles)
948 : {
949 4 : for( unsigned int iOver = 0; iOver < apoOverviews.size(); iOver++ )
950 : {
951 0 : CPLString &osFilename = apoOverviews[iOver].osFilename;
952 :
953 : /* -------------------------------------------------------------------- */
954 : /* Is the filename even a real filesystem object? */
955 : /* -------------------------------------------------------------------- */
956 : VSIStatBufL sStat;
957 0 : if( VSIStatL( osFilename, &sStat ) != 0 )
958 0 : return;
959 :
960 : /* -------------------------------------------------------------------- */
961 : /* Is it already in the list ? */
962 : /* -------------------------------------------------------------------- */
963 0 : if( CPLHashSetLookup(hSetFiles, osFilename) != NULL )
964 0 : return;
965 :
966 : /* -------------------------------------------------------------------- */
967 : /* Grow array if necessary */
968 : /* -------------------------------------------------------------------- */
969 0 : if (*pnSize + 1 >= *pnMaxSize)
970 : {
971 0 : *pnMaxSize = 2 + 2 * (*pnMaxSize);
972 : *ppapszFileList = (char **) CPLRealloc(
973 0 : *ppapszFileList, sizeof(char*) * (*pnMaxSize) );
974 : }
975 :
976 : /* -------------------------------------------------------------------- */
977 : /* Add the string to the list */
978 : /* -------------------------------------------------------------------- */
979 0 : (*ppapszFileList)[*pnSize] = CPLStrdup(osFilename);
980 0 : (*ppapszFileList)[(*pnSize + 1)] = NULL;
981 0 : CPLHashSetInsert(hSetFiles, (*ppapszFileList)[*pnSize]);
982 :
983 0 : (*pnSize) ++;
984 : }
985 : }
986 :
987 : /************************************************************************/
988 : /* GetOverviewCount() */
989 : /************************************************************************/
990 :
991 2832 : int VRTRasterBand::GetOverviewCount()
992 :
993 : {
994 2832 : if( apoOverviews.size() > 0 )
995 10 : return apoOverviews.size();
996 : else
997 2822 : return GDALRasterBand::GetOverviewCount();
998 : }
999 :
1000 : /************************************************************************/
1001 : /* GetOverview() */
1002 : /************************************************************************/
1003 :
1004 42 : GDALRasterBand *VRTRasterBand::GetOverview( int iOverview )
1005 :
1006 : {
1007 42 : if( apoOverviews.size() > 0 )
1008 : {
1009 5 : if( iOverview < 0 || iOverview >= (int) apoOverviews.size() )
1010 0 : return NULL;
1011 :
1012 5 : if( apoOverviews[iOverview].poBand == NULL
1013 : && !apoOverviews[iOverview].bTriedToOpen )
1014 : {
1015 5 : apoOverviews[iOverview].bTriedToOpen = TRUE;
1016 :
1017 : GDALDataset *poSrcDS = (GDALDataset *)
1018 5 : GDALOpenShared( apoOverviews[iOverview].osFilename, GA_ReadOnly );
1019 :
1020 5 : if( poSrcDS == NULL )
1021 0 : return NULL;
1022 :
1023 : apoOverviews[iOverview].poBand = poSrcDS->GetRasterBand(
1024 5 : apoOverviews[iOverview].nBand );
1025 :
1026 5 : if (apoOverviews[iOverview].poBand == NULL)
1027 : {
1028 0 : GDALClose( (GDALDatasetH)poSrcDS );
1029 : }
1030 : }
1031 :
1032 5 : return apoOverviews[iOverview].poBand;
1033 : }
1034 : else
1035 37 : return GDALRasterBand::GetOverview( iOverview );
1036 : }
1037 :
1038 : /************************************************************************/
1039 : /* SetDescription() */
1040 : /************************************************************************/
1041 :
1042 565 : void VRTRasterBand::SetDescription(const char* pszDescription)
1043 :
1044 : {
1045 565 : ((VRTDataset *)poDS)->SetNeedsFlush();
1046 :
1047 565 : GDALRasterBand::SetDescription(pszDescription);
1048 565 : }
1049 :
1050 : /************************************************************************/
1051 : /* CreateMaskBand() */
1052 : /************************************************************************/
1053 :
1054 0 : CPLErr VRTRasterBand::CreateMaskBand( int nFlags )
1055 : {
1056 0 : VRTDataset* poGDS = (VRTDataset *)poDS;
1057 :
1058 0 : if (poGDS->poMaskBand)
1059 : {
1060 : CPLError( CE_Failure, CPLE_AppDefined,
1061 0 : "Cannot create mask band at raster band level when a dataset mask band already exists." );
1062 0 : return CE_Failure;
1063 : }
1064 :
1065 0 : if (poMaskBand != NULL)
1066 : {
1067 : CPLError(CE_Failure, CPLE_AppDefined,
1068 0 : "This VRT band has already a mask band");
1069 0 : return CE_Failure;
1070 : }
1071 :
1072 0 : if ((nFlags & GMF_PER_DATASET) != 0)
1073 0 : return poGDS->CreateMaskBand(nFlags);
1074 :
1075 0 : SetMaskBand(new VRTSourcedRasterBand( poGDS, 0 ));
1076 :
1077 0 : return CE_None;
1078 : }
1079 :
1080 : /************************************************************************/
1081 : /* GetMaskBand() */
1082 : /************************************************************************/
1083 :
1084 171 : GDALRasterBand* VRTRasterBand::GetMaskBand()
1085 : {
1086 171 : VRTDataset* poGDS = (VRTDataset *)poDS;
1087 171 : if (poGDS->poMaskBand)
1088 10 : return poGDS->poMaskBand;
1089 161 : else if (poMaskBand)
1090 1 : return poMaskBand;
1091 : else
1092 160 : return GDALRasterBand::GetMaskBand();
1093 : }
1094 :
1095 : /************************************************************************/
1096 : /* GetMaskFlags() */
1097 : /************************************************************************/
1098 :
1099 339 : int VRTRasterBand::GetMaskFlags()
1100 : {
1101 339 : VRTDataset* poGDS = (VRTDataset *)poDS;
1102 339 : if (poGDS->poMaskBand)
1103 1 : return GMF_PER_DATASET;
1104 338 : else if (poMaskBand)
1105 1 : return 0;
1106 : else
1107 337 : return GDALRasterBand::GetMaskFlags();
1108 : }
1109 :
1110 : /************************************************************************/
1111 : /* SetMaskBand() */
1112 : /************************************************************************/
1113 :
1114 1 : void VRTRasterBand::SetMaskBand(VRTRasterBand* poMaskBand)
1115 : {
1116 1 : delete this->poMaskBand;
1117 1 : this->poMaskBand = poMaskBand;
1118 1 : poMaskBand->SetIsMaskBand();
1119 1 : }
1120 :
1121 : /************************************************************************/
1122 : /* SetIsMaskBand() */
1123 : /************************************************************************/
1124 :
1125 16 : void VRTRasterBand::SetIsMaskBand()
1126 : {
1127 16 : nBand = 0;
1128 16 : bIsMaskBand = TRUE;
1129 16 : }
1130 :
1131 : /************************************************************************/
1132 : /* CloseDependentDatasets() */
1133 : /************************************************************************/
1134 :
1135 110 : int VRTRasterBand::CloseDependentDatasets()
1136 : {
1137 110 : return FALSE;
1138 : }
|