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 749 : VRTRasterBand::VRTRasterBand()
47 :
48 : {
49 749 : Initialize( 0, 0 );
50 749 : }
51 :
52 : /************************************************************************/
53 : /* Initialize() */
54 : /************************************************************************/
55 :
56 1498 : void VRTRasterBand::Initialize( int nXSize, int nYSize )
57 :
58 : {
59 1498 : poDS = NULL;
60 1498 : nBand = 0;
61 1498 : eAccess = GA_ReadOnly;
62 1498 : eDataType = GDT_Byte;
63 :
64 1498 : nRasterXSize = nXSize;
65 1498 : nRasterYSize = nYSize;
66 :
67 1498 : nBlockXSize = MIN(128,nXSize);
68 1498 : nBlockYSize = MIN(128,nYSize);
69 :
70 1498 : bIsMaskBand = FALSE;
71 1498 : bNoDataValueSet = FALSE;
72 1498 : bHideNoDataValue = FALSE;
73 1498 : dfNoDataValue = -10000.0;
74 1498 : poColorTable = NULL;
75 1498 : eColorInterp = GCI_Undefined;
76 :
77 1498 : pszUnitType = NULL;
78 1498 : papszCategoryNames = NULL;
79 1498 : dfOffset = 0.0;
80 1498 : dfScale = 1.0;
81 :
82 1498 : psSavedHistograms = NULL;
83 :
84 1498 : poMaskBand = NULL;
85 1498 : }
86 :
87 : /************************************************************************/
88 : /* ~VRTRasterBand() */
89 : /************************************************************************/
90 :
91 749 : VRTRasterBand::~VRTRasterBand()
92 :
93 : {
94 749 : CPLFree( pszUnitType );
95 :
96 749 : if( poColorTable != NULL )
97 12 : delete poColorTable;
98 :
99 749 : CSLDestroy( papszCategoryNames );
100 749 : if( psSavedHistograms != NULL )
101 0 : CPLDestroyXMLNode( psSavedHistograms );
102 :
103 749 : delete poMaskBand;
104 749 : }
105 :
106 : /************************************************************************/
107 : /* CopyCommonInfoFrom() */
108 : /* */
109 : /* Copy common metadata, pixel descriptions, and color */
110 : /* interpretation from the provided source band. */
111 : /************************************************************************/
112 :
113 118 : CPLErr VRTRasterBand::CopyCommonInfoFrom( GDALRasterBand * poSrcBand )
114 :
115 : {
116 : int bSuccess;
117 : double dfNoData;
118 :
119 118 : SetMetadata( poSrcBand->GetMetadata() );
120 118 : SetColorTable( poSrcBand->GetColorTable() );
121 118 : SetColorInterpretation(poSrcBand->GetColorInterpretation());
122 118 : if( strlen(poSrcBand->GetDescription()) > 0 )
123 1 : SetDescription( poSrcBand->GetDescription() );
124 118 : dfNoData = poSrcBand->GetNoDataValue( &bSuccess );
125 118 : if( bSuccess )
126 0 : SetNoDataValue( dfNoData );
127 :
128 118 : SetOffset( poSrcBand->GetOffset() );
129 118 : SetScale( poSrcBand->GetScale() );
130 118 : SetCategoryNames( poSrcBand->GetCategoryNames() );
131 118 : if( !EQUAL(poSrcBand->GetUnitType(),"") )
132 1 : SetUnitType( poSrcBand->GetUnitType() );
133 :
134 118 : return CE_None;
135 : }
136 :
137 : /************************************************************************/
138 : /* SetMetadata() */
139 : /************************************************************************/
140 :
141 181 : CPLErr VRTRasterBand::SetMetadata( char **papszMetadata,
142 : const char *pszDomain )
143 :
144 : {
145 181 : ((VRTDataset *) poDS)->SetNeedsFlush();
146 :
147 181 : return GDALRasterBand::SetMetadata( papszMetadata, pszDomain );
148 : }
149 :
150 : /************************************************************************/
151 : /* SetMetadataItem() */
152 : /************************************************************************/
153 :
154 14 : CPLErr VRTRasterBand::SetMetadataItem( const char *pszName,
155 : const char *pszValue,
156 : const char *pszDomain )
157 :
158 : {
159 14 : ((VRTDataset *) poDS)->SetNeedsFlush();
160 :
161 14 : if( EQUAL(pszName,"HideNoDataValue") )
162 : {
163 0 : bHideNoDataValue = CSLTestBoolean( pszValue );
164 0 : return CE_None;
165 : }
166 : else
167 14 : return GDALRasterBand::SetMetadataItem( pszName, pszValue, pszDomain );
168 : }
169 :
170 : /************************************************************************/
171 : /* GetUnitType() */
172 : /************************************************************************/
173 :
174 271 : const char *VRTRasterBand::GetUnitType()
175 :
176 : {
177 271 : if( pszUnitType == NULL )
178 267 : return "";
179 : else
180 4 : return pszUnitType;
181 : }
182 :
183 : /************************************************************************/
184 : /* SetUnitType() */
185 : /************************************************************************/
186 :
187 426 : CPLErr VRTRasterBand::SetUnitType( const char *pszNewValue )
188 :
189 : {
190 426 : ((VRTDataset *) poDS)->SetNeedsFlush();
191 :
192 426 : CPLFree( pszUnitType );
193 :
194 426 : if( pszNewValue == NULL )
195 423 : pszUnitType = NULL;
196 : else
197 3 : pszUnitType = CPLStrdup(pszNewValue);
198 :
199 426 : return CE_None;
200 : }
201 :
202 : /************************************************************************/
203 : /* GetOffset() */
204 : /************************************************************************/
205 :
206 274 : double VRTRasterBand::GetOffset( int *pbSuccess )
207 :
208 : {
209 274 : if( pbSuccess != NULL )
210 269 : *pbSuccess = TRUE;
211 :
212 274 : return dfOffset;
213 : }
214 :
215 : /************************************************************************/
216 : /* SetOffset() */
217 : /************************************************************************/
218 :
219 605 : CPLErr VRTRasterBand::SetOffset( double dfNewOffset )
220 :
221 : {
222 605 : ((VRTDataset *) poDS)->SetNeedsFlush();
223 :
224 605 : dfOffset = dfNewOffset;
225 605 : return CE_None;
226 : }
227 :
228 : /************************************************************************/
229 : /* GetScale() */
230 : /************************************************************************/
231 :
232 274 : double VRTRasterBand::GetScale( int *pbSuccess )
233 :
234 : {
235 274 : if( pbSuccess != NULL )
236 148 : *pbSuccess = TRUE;
237 :
238 274 : return dfScale;
239 : }
240 :
241 : /************************************************************************/
242 : /* SetScale() */
243 : /************************************************************************/
244 :
245 605 : CPLErr VRTRasterBand::SetScale( double dfNewScale )
246 :
247 : {
248 605 : ((VRTDataset *) poDS)->SetNeedsFlush();
249 :
250 605 : dfScale = dfNewScale;
251 605 : return CE_None;
252 : }
253 :
254 : /************************************************************************/
255 : /* GetCategoryNames() */
256 : /************************************************************************/
257 :
258 273 : char **VRTRasterBand::GetCategoryNames()
259 :
260 : {
261 273 : return papszCategoryNames;
262 : }
263 :
264 : /************************************************************************/
265 : /* SetCategoryNames() */
266 : /************************************************************************/
267 :
268 181 : CPLErr VRTRasterBand::SetCategoryNames( char ** papszNewNames )
269 :
270 : {
271 181 : ((VRTDataset *) poDS)->SetNeedsFlush();
272 :
273 181 : CSLDestroy( papszCategoryNames );
274 181 : papszCategoryNames = CSLDuplicate( papszNewNames );
275 :
276 181 : return CE_None;
277 : }
278 :
279 : /************************************************************************/
280 : /* XMLInit() */
281 : /************************************************************************/
282 :
283 424 : CPLErr VRTRasterBand::XMLInit( CPLXMLNode * psTree,
284 : const char *pszVRTPath )
285 :
286 : {
287 : /* -------------------------------------------------------------------- */
288 : /* Validate a bit. */
289 : /* -------------------------------------------------------------------- */
290 424 : 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 424 : const char* pszBand = CPLGetXMLValue( psTree, "band", NULL);
302 424 : if( pszBand != NULL )
303 : {
304 413 : nBand = atoi(pszBand);
305 : }
306 :
307 : /* -------------------------------------------------------------------- */
308 : /* Set the band if provided as an attribute. */
309 : /* -------------------------------------------------------------------- */
310 424 : const char *pszDataType = CPLGetXMLValue( psTree, "dataType", NULL);
311 424 : if( pszDataType != NULL )
312 : {
313 424 : eDataType = GDALGetDataTypeByName(pszDataType);
314 : }
315 :
316 : /* -------------------------------------------------------------------- */
317 : /* Apply any band level metadata. */
318 : /* -------------------------------------------------------------------- */
319 424 : oMDMD.XMLInit( psTree, TRUE );
320 :
321 : /* -------------------------------------------------------------------- */
322 : /* Collect various other items of metadata. */
323 : /* -------------------------------------------------------------------- */
324 424 : SetDescription( CPLGetXMLValue( psTree, "Description", "" ) );
325 :
326 424 : if( CPLGetXMLValue( psTree, "NoDataValue", NULL ) != NULL )
327 45 : SetNoDataValue( CPLAtofM(CPLGetXMLValue( psTree, "NoDataValue", "0" )) );
328 :
329 424 : if( CPLGetXMLValue( psTree, "HideNoDataValue", NULL ) != NULL )
330 0 : bHideNoDataValue = CSLTestBoolean( CPLGetXMLValue( psTree, "HideNoDataValue", "0" ) );
331 :
332 424 : SetUnitType( CPLGetXMLValue( psTree, "UnitType", NULL ) );
333 :
334 424 : SetOffset( atof(CPLGetXMLValue( psTree, "Offset", "0.0" )) );
335 424 : SetScale( atof(CPLGetXMLValue( psTree, "Scale", "1.0" )) );
336 :
337 424 : if( CPLGetXMLValue( psTree, "ColorInterp", NULL ) != NULL )
338 : {
339 286 : const char *pszInterp = CPLGetXMLValue( psTree, "ColorInterp", NULL );
340 286 : SetColorInterpretation(GDALGetColorInterpretationByName(pszInterp));
341 : }
342 :
343 : /* -------------------------------------------------------------------- */
344 : /* Category names. */
345 : /* -------------------------------------------------------------------- */
346 424 : 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 424 : 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 424 : CPLXMLNode *psHist = CPLGetXMLNode( psTree, "Histograms" );
399 424 : 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 2253 : for( psNode = psTree->psChild; psNode != NULL; psNode = psNode->psNext )
414 : {
415 1829 : if( psNode->eType != CXT_Element
416 : || !EQUAL(psNode->pszValue,"Overview") )
417 1823 : continue;
418 :
419 : /* -------------------------------------------------------------------- */
420 : /* Prepare filename. */
421 : /* -------------------------------------------------------------------- */
422 6 : char *pszSrcDSName = NULL;
423 6 : CPLXMLNode* psFileNameNode=CPLGetXMLNode(psNode,"SourceFilename");
424 : const char *pszFilename =
425 6 : psFileNameNode ? CPLGetXMLValue(psFileNameNode,NULL, NULL) : NULL;
426 :
427 6 : 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 6 : 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 6 : if( pszVRTPath != NULL
444 : && atoi(CPLGetXMLValue( psFileNameNode, "relativetoVRT", "0")) )
445 : {
446 : pszSrcDSName = CPLStrdup(
447 0 : CPLProjectRelativeFilename( pszVRTPath, pszFilename ) );
448 : }
449 : else
450 6 : pszSrcDSName = CPLStrdup( pszFilename );
451 :
452 : /* -------------------------------------------------------------------- */
453 : /* Get the raster band. */
454 : /* -------------------------------------------------------------------- */
455 6 : int nSrcBand = atoi(CPLGetXMLValue(psNode,"SourceBand","1"));
456 :
457 6 : apoOverviews.resize( apoOverviews.size() + 1 );
458 12 : apoOverviews[apoOverviews.size()-1].osFilename = pszSrcDSName;
459 6 : apoOverviews[apoOverviews.size()-1].nBand = nSrcBand;
460 :
461 6 : CPLFree( pszSrcDSName );
462 : }
463 :
464 : /* ==================================================================== */
465 : /* Mask band (specific to that raster band) */
466 : /* ==================================================================== */
467 424 : CPLXMLNode* psMaskBandNode = CPLGetXMLNode(psTree, "MaskBand");
468 424 : if (psMaskBandNode)
469 1 : psNode = psMaskBandNode->psChild;
470 : else
471 423 : psNode = NULL;
472 848 : 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 424 : return CE_None;
515 : }
516 :
517 : /************************************************************************/
518 : /* SerializeToXML() */
519 : /************************************************************************/
520 :
521 221 : CPLXMLNode *VRTRasterBand::SerializeToXML( const char *pszVRTPath )
522 :
523 : {
524 : CPLXMLNode *psTree;
525 :
526 221 : psTree = CPLCreateXMLNode( NULL, CXT_Element, "VRTRasterBand" );
527 :
528 : /* -------------------------------------------------------------------- */
529 : /* Various kinds of metadata. */
530 : /* -------------------------------------------------------------------- */
531 : CPLXMLNode *psMD;
532 :
533 : CPLSetXMLValue( psTree, "#dataType",
534 221 : GDALGetDataTypeName( GetRasterDataType() ) );
535 :
536 221 : if( nBand > 0 )
537 215 : CPLSetXMLValue( psTree, "#band", CPLSPrintf( "%d", GetBand() ) );
538 :
539 221 : psMD = oMDMD.Serialize();
540 221 : if( psMD != NULL )
541 120 : CPLAddXMLChild( psTree, psMD );
542 :
543 221 : if( strlen(GetDescription()) > 0 )
544 3 : CPLSetXMLValue( psTree, "Description", GetDescription() );
545 :
546 221 : 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 221 : if( bHideNoDataValue )
556 : CPLSetXMLValue( psTree, "HideNoDataValue",
557 0 : CPLSPrintf( "%d", bHideNoDataValue ) );
558 :
559 221 : if( pszUnitType != NULL )
560 1 : CPLSetXMLValue( psTree, "UnitType", pszUnitType );
561 :
562 221 : if( dfOffset != 0.0 )
563 : CPLSetXMLValue( psTree, "Offset",
564 1 : CPLSPrintf( "%.16g", dfOffset ) );
565 :
566 221 : if( dfScale != 1.0 )
567 : CPLSetXMLValue( psTree, "Scale",
568 1 : CPLSPrintf( "%.16g", dfScale ) );
569 :
570 221 : if( eColorInterp != GCI_Undefined )
571 : CPLSetXMLValue( psTree, "ColorInterp",
572 136 : GDALGetColorInterpretationName( eColorInterp ) );
573 :
574 : /* -------------------------------------------------------------------- */
575 : /* Category names. */
576 : /* -------------------------------------------------------------------- */
577 221 : 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 221 : if( psSavedHistograms != NULL )
599 0 : CPLAddXMLChild( psTree, CPLCloneXMLTree( psSavedHistograms ) );
600 :
601 : /* -------------------------------------------------------------------- */
602 : /* Color Table. */
603 : /* -------------------------------------------------------------------- */
604 221 : 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 222 : 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 221 : 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 221 : return psTree;
685 : }
686 :
687 : /************************************************************************/
688 : /* SetNoDataValue() */
689 : /************************************************************************/
690 :
691 57 : CPLErr VRTRasterBand::SetNoDataValue( double dfNewValue )
692 :
693 : {
694 57 : bNoDataValueSet = TRUE;
695 57 : dfNoDataValue = dfNewValue;
696 :
697 57 : ((VRTDataset *)poDS)->SetNeedsFlush();
698 :
699 57 : 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 474 : double VRTRasterBand::GetNoDataValue( int *pbSuccess )
721 :
722 : {
723 474 : if( pbSuccess )
724 441 : *pbSuccess = bNoDataValueSet && !bHideNoDataValue;
725 :
726 474 : return dfNoDataValue;
727 : }
728 :
729 : /************************************************************************/
730 : /* SetColorTable() */
731 : /************************************************************************/
732 :
733 191 : CPLErr VRTRasterBand::SetColorTable( GDALColorTable *poTableIn )
734 :
735 : {
736 191 : if( poColorTable != NULL )
737 : {
738 0 : delete poColorTable;
739 0 : poColorTable = NULL;
740 : }
741 :
742 191 : if( poTableIn )
743 : {
744 12 : poColorTable = poTableIn->Clone();
745 12 : eColorInterp = GCI_PaletteIndex;
746 : }
747 :
748 191 : ((VRTDataset *)poDS)->SetNeedsFlush();
749 :
750 191 : return CE_None;
751 : }
752 :
753 : /************************************************************************/
754 : /* GetColorTable() */
755 : /************************************************************************/
756 :
757 373 : GDALColorTable *VRTRasterBand::GetColorTable()
758 :
759 : {
760 373 : return poColorTable;
761 : }
762 :
763 : /************************************************************************/
764 : /* SetColorInterpretation() */
765 : /************************************************************************/
766 :
767 531 : CPLErr VRTRasterBand::SetColorInterpretation( GDALColorInterp eInterpIn )
768 :
769 : {
770 531 : ((VRTDataset *)poDS)->SetNeedsFlush();
771 :
772 531 : eColorInterp = eInterpIn;
773 :
774 531 : return CE_None;
775 : }
776 :
777 : /************************************************************************/
778 : /* GetColorInterpretation() */
779 : /************************************************************************/
780 :
781 345 : GDALColorInterp VRTRasterBand::GetColorInterpretation()
782 :
783 : {
784 345 : 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 288 : int VRTRasterBand::GetOverviewCount()
992 :
993 : {
994 288 : if( apoOverviews.size() > 0 )
995 6 : return apoOverviews.size();
996 : else
997 282 : return GDALRasterBand::GetOverviewCount();
998 : }
999 :
1000 : /************************************************************************/
1001 : /* GetOverview() */
1002 : /************************************************************************/
1003 :
1004 41 : GDALRasterBand *VRTRasterBand::GetOverview( int iOverview )
1005 :
1006 : {
1007 41 : if( apoOverviews.size() > 0 )
1008 : {
1009 4 : if( iOverview < 0 || iOverview >= (int) apoOverviews.size() )
1010 0 : return NULL;
1011 :
1012 4 : if( apoOverviews[iOverview].poBand == NULL
1013 : && !apoOverviews[iOverview].bTriedToOpen )
1014 : {
1015 4 : apoOverviews[iOverview].bTriedToOpen = TRUE;
1016 :
1017 : GDALDataset *poSrcDS = (GDALDataset *)
1018 4 : GDALOpenShared( apoOverviews[iOverview].osFilename, GA_ReadOnly );
1019 :
1020 4 : if( poSrcDS == NULL )
1021 0 : return NULL;
1022 :
1023 : apoOverviews[iOverview].poBand = poSrcDS->GetRasterBand(
1024 4 : apoOverviews[iOverview].nBand );
1025 :
1026 4 : if (apoOverviews[iOverview].poBand == NULL)
1027 : {
1028 0 : GDALClose( (GDALDatasetH)poSrcDS );
1029 : }
1030 : }
1031 :
1032 4 : return apoOverviews[iOverview].poBand;
1033 : }
1034 : else
1035 37 : return GDALRasterBand::GetOverview( iOverview );
1036 : }
1037 :
1038 : /************************************************************************/
1039 : /* SetDescription() */
1040 : /************************************************************************/
1041 :
1042 428 : void VRTRasterBand::SetDescription(const char* pszDescription)
1043 :
1044 : {
1045 428 : ((VRTDataset *)poDS)->SetNeedsFlush();
1046 :
1047 428 : GDALRasterBand::SetDescription(pszDescription);
1048 428 : }
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 167 : GDALRasterBand* VRTRasterBand::GetMaskBand()
1085 : {
1086 167 : VRTDataset* poGDS = (VRTDataset *)poDS;
1087 167 : if (poGDS->poMaskBand)
1088 10 : return poGDS->poMaskBand;
1089 157 : else if (poMaskBand)
1090 1 : return poMaskBand;
1091 : else
1092 156 : return GDALRasterBand::GetMaskBand();
1093 : }
1094 :
1095 : /************************************************************************/
1096 : /* GetMaskFlags() */
1097 : /************************************************************************/
1098 :
1099 330 : int VRTRasterBand::GetMaskFlags()
1100 : {
1101 330 : VRTDataset* poGDS = (VRTDataset *)poDS;
1102 330 : if (poGDS->poMaskBand)
1103 1 : return GMF_PER_DATASET;
1104 329 : else if (poMaskBand)
1105 1 : return 0;
1106 : else
1107 328 : 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 88 : int VRTRasterBand::CloseDependentDatasets()
1136 : {
1137 88 : return FALSE;
1138 : }
|