1 : /******************************************************************************
2 : * $Id: gdalpamrasterband.cpp 23851 2012-01-31 21:15:24Z rouault $
3 : *
4 : * Project: GDAL Core
5 : * Purpose: Implementation of GDALPamRasterBand, a raster band base class
6 : * that knows how to persistently store auxilary metadata in an
7 : * external xml file.
8 : * Author: Frank Warmerdam, warmerdam@pobox.com
9 : *
10 : ******************************************************************************
11 : * Copyright (c) 2005, Frank Warmerdam <warmerdam@pobox.com>
12 : *
13 : * Permission is hereby granted, free of charge, to any person obtaining a
14 : * copy of this software and associated documentation files (the "Software"),
15 : * to deal in the Software without restriction, including without limitation
16 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 : * and/or sell copies of the Software, and to permit persons to whom the
18 : * Software is furnished to do so, subject to the following conditions:
19 : *
20 : * The above copyright notice and this permission notice shall be included
21 : * in all copies or substantial portions of the Software.
22 : *
23 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 : * DEALINGS IN THE SOFTWARE.
30 : ****************************************************************************/
31 :
32 : #include "gdal_pam.h"
33 : #include "gdal_rat.h"
34 : #include "cpl_string.h"
35 :
36 : CPL_CVSID("$Id: gdalpamrasterband.cpp 23851 2012-01-31 21:15:24Z rouault $");
37 :
38 : /************************************************************************/
39 : /* GDALPamRasterBand() */
40 : /************************************************************************/
41 :
42 623258 : GDALPamRasterBand::GDALPamRasterBand()
43 :
44 : {
45 623258 : psPam = NULL;
46 623258 : SetMOFlags( GetMOFlags() | GMO_PAM_CLASS );
47 623258 : }
48 :
49 : /************************************************************************/
50 : /* ~GDALPamRasterBand() */
51 : /************************************************************************/
52 :
53 623258 : GDALPamRasterBand::~GDALPamRasterBand()
54 :
55 : {
56 623258 : PamClear();
57 623258 : }
58 :
59 : /************************************************************************/
60 : /* SerializeToXML() */
61 : /************************************************************************/
62 :
63 1202 : CPLXMLNode *GDALPamRasterBand::SerializeToXML( const char *pszUnused )
64 :
65 : {
66 1202 : if( psPam == NULL )
67 19 : return NULL;
68 :
69 : /* -------------------------------------------------------------------- */
70 : /* Setup root node and attributes. */
71 : /* -------------------------------------------------------------------- */
72 1183 : CPLString oFmt;
73 :
74 : CPLXMLNode *psTree;
75 :
76 1183 : psTree = CPLCreateXMLNode( NULL, CXT_Element, "PAMRasterBand" );
77 :
78 1183 : if( GetBand() > 0 )
79 1183 : CPLSetXMLValue( psTree, "#band", oFmt.Printf( "%d", GetBand() ) );
80 :
81 : /* -------------------------------------------------------------------- */
82 : /* Serialize information of interest. */
83 : /* -------------------------------------------------------------------- */
84 1183 : if( strlen(GetDescription()) > 0 )
85 100 : CPLSetXMLValue( psTree, "Description", GetDescription() );
86 :
87 1183 : if( psPam->bNoDataValueSet )
88 : {
89 73 : if (CPLIsNan(psPam->dfNoDataValue))
90 3 : CPLSetXMLValue( psTree, "NoDataValue", "nan" );
91 : else
92 : CPLSetXMLValue( psTree, "NoDataValue",
93 70 : oFmt.Printf( "%.14E", psPam->dfNoDataValue ) );
94 :
95 : /* hex encode real floating point values */
96 73 : if( psPam->dfNoDataValue != floor(psPam->dfNoDataValue)
97 : || psPam->dfNoDataValue != atof(oFmt) )
98 : {
99 : double dfNoDataLittleEndian;
100 :
101 15 : dfNoDataLittleEndian = psPam->dfNoDataValue;
102 : CPL_LSBPTR64( &dfNoDataLittleEndian );
103 :
104 : char *pszHexEncoding =
105 15 : CPLBinaryToHex( 8, (GByte *) &dfNoDataLittleEndian );
106 15 : CPLSetXMLValue( psTree, "NoDataValue.#le_hex_equiv",pszHexEncoding);
107 15 : CPLFree( pszHexEncoding );
108 : }
109 : }
110 :
111 1183 : if( psPam->pszUnitType != NULL )
112 3 : CPLSetXMLValue( psTree, "UnitType", psPam->pszUnitType );
113 :
114 1183 : if( psPam->dfOffset != 0.0 )
115 : CPLSetXMLValue( psTree, "Offset",
116 2 : oFmt.Printf( "%.16g", psPam->dfOffset ) );
117 :
118 1183 : if( psPam->dfScale != 1.0 )
119 : CPLSetXMLValue( psTree, "Scale",
120 2 : oFmt.Printf( "%.16g", psPam->dfScale ) );
121 :
122 1183 : if( psPam->eColorInterp != GCI_Undefined )
123 : CPLSetXMLValue( psTree, "ColorInterp",
124 315 : GDALGetColorInterpretationName( psPam->eColorInterp ));
125 :
126 : /* -------------------------------------------------------------------- */
127 : /* Category names. */
128 : /* -------------------------------------------------------------------- */
129 1183 : if( psPam->papszCategoryNames != NULL )
130 : {
131 : CPLXMLNode *psCT_XML = CPLCreateXMLNode( psTree, CXT_Element,
132 1 : "CategoryNames" );
133 1 : CPLXMLNode* psLastChild = NULL;
134 :
135 3 : for( int iEntry=0; psPam->papszCategoryNames[iEntry] != NULL; iEntry++)
136 : {
137 : CPLXMLNode *psNode = CPLCreateXMLElementAndValue( NULL, "Category",
138 2 : psPam->papszCategoryNames[iEntry] );
139 2 : if( psLastChild == NULL )
140 1 : psCT_XML->psChild = psNode;
141 : else
142 1 : psLastChild->psNext = psNode;
143 2 : psLastChild = psNode;
144 : }
145 : }
146 :
147 : /* -------------------------------------------------------------------- */
148 : /* Color Table. */
149 : /* -------------------------------------------------------------------- */
150 1183 : if( psPam->poColorTable != NULL )
151 : {
152 : CPLXMLNode *psCT_XML = CPLCreateXMLNode( psTree, CXT_Element,
153 1 : "ColorTable" );
154 1 : CPLXMLNode* psLastChild = NULL;
155 :
156 3 : for( int iEntry=0; iEntry < psPam->poColorTable->GetColorEntryCount();
157 : iEntry++ )
158 : {
159 : GDALColorEntry sEntry;
160 : CPLXMLNode *psEntry_XML = CPLCreateXMLNode( NULL, CXT_Element,
161 2 : "Entry" );
162 2 : if( psLastChild == NULL )
163 1 : psCT_XML->psChild = psEntry_XML;
164 : else
165 1 : psLastChild->psNext = psEntry_XML;
166 2 : psLastChild = psEntry_XML;
167 :
168 2 : psPam->poColorTable->GetColorEntryAsRGB( iEntry, &sEntry );
169 :
170 2 : CPLSetXMLValue( psEntry_XML, "#c1", oFmt.Printf("%d",sEntry.c1) );
171 2 : CPLSetXMLValue( psEntry_XML, "#c2", oFmt.Printf("%d",sEntry.c2) );
172 2 : CPLSetXMLValue( psEntry_XML, "#c3", oFmt.Printf("%d",sEntry.c3) );
173 2 : CPLSetXMLValue( psEntry_XML, "#c4", oFmt.Printf("%d",sEntry.c4) );
174 : }
175 : }
176 :
177 : /* -------------------------------------------------------------------- */
178 : /* Min/max. */
179 : /* -------------------------------------------------------------------- */
180 1183 : if( psPam->bHaveMinMax )
181 : {
182 : CPLSetXMLValue( psTree, "Minimum",
183 0 : oFmt.Printf( "%.16g", psPam->dfMin ) );
184 : CPLSetXMLValue( psTree, "Maximum",
185 0 : oFmt.Printf( "%.16g", psPam->dfMax ) );
186 : }
187 :
188 : /* -------------------------------------------------------------------- */
189 : /* Statistics */
190 : /* -------------------------------------------------------------------- */
191 1183 : if( psPam->bHaveStats )
192 : {
193 : CPLSetXMLValue( psTree, "Mean",
194 0 : oFmt.Printf( "%.16g", psPam->dfMean ) );
195 : CPLSetXMLValue( psTree, "StandardDeviation",
196 0 : oFmt.Printf( "%.16g", psPam->dfStdDev ) );
197 : }
198 :
199 : /* -------------------------------------------------------------------- */
200 : /* Histograms. */
201 : /* -------------------------------------------------------------------- */
202 1183 : if( psPam->psSavedHistograms != NULL )
203 9 : CPLAddXMLChild( psTree, CPLCloneXMLTree( psPam->psSavedHistograms ) );
204 :
205 : /* -------------------------------------------------------------------- */
206 : /* Raster Attribute Table */
207 : /* -------------------------------------------------------------------- */
208 1183 : if( psPam->poDefaultRAT != NULL )
209 4 : CPLAddXMLChild( psTree, psPam->poDefaultRAT->Serialize() );
210 :
211 : /* -------------------------------------------------------------------- */
212 : /* Metadata. */
213 : /* -------------------------------------------------------------------- */
214 : CPLXMLNode *psMD;
215 :
216 1183 : psMD = oMDMD.Serialize();
217 1183 : if( psMD != NULL )
218 : {
219 321 : if( psMD->psChild == NULL )
220 3 : CPLDestroyXMLNode( psMD );
221 : else
222 318 : CPLAddXMLChild( psTree, psMD );
223 : }
224 :
225 : /* -------------------------------------------------------------------- */
226 : /* We don't want to return anything if we had no metadata to */
227 : /* attach. */
228 : /* -------------------------------------------------------------------- */
229 1183 : if( psTree->psChild == NULL || psTree->psChild->psNext == NULL )
230 : {
231 532 : CPLDestroyXMLNode( psTree );
232 532 : psTree = NULL;
233 : }
234 :
235 1183 : return psTree;
236 : }
237 :
238 : /************************************************************************/
239 : /* PamInitialize() */
240 : /************************************************************************/
241 :
242 489813 : void GDALPamRasterBand::PamInitialize()
243 :
244 : {
245 489813 : if( psPam )
246 6872 : return;
247 :
248 482941 : GDALPamDataset *poParentDS = (GDALPamDataset *) GetDataset();
249 :
250 482941 : if( poParentDS == NULL || !(poParentDS->GetMOFlags() & GMO_PAM_CLASS) )
251 124 : return;
252 :
253 482817 : poParentDS->PamInitialize();
254 482817 : if( poParentDS->psPam == NULL )
255 11 : return;
256 :
257 : // Often (always?) initializing our parent will have initialized us.
258 482806 : if( psPam != NULL )
259 470 : return;
260 :
261 : psPam = (GDALRasterBandPamInfo *)
262 482336 : CPLCalloc(sizeof(GDALRasterBandPamInfo),1);
263 :
264 482336 : psPam->dfScale = 1.0;
265 482336 : psPam->poParentDS = poParentDS;
266 482336 : psPam->dfNoDataValue = -1e10;
267 482336 : psPam->poDefaultRAT = NULL;
268 : }
269 :
270 : /************************************************************************/
271 : /* PamClear() */
272 : /************************************************************************/
273 :
274 623258 : void GDALPamRasterBand::PamClear()
275 :
276 : {
277 623258 : if( psPam )
278 : {
279 482336 : if( psPam->poColorTable )
280 4 : delete psPam->poColorTable;
281 482336 : psPam->poColorTable = NULL;
282 :
283 482336 : CPLFree( psPam->pszUnitType );
284 482336 : CSLDestroy( psPam->papszCategoryNames );
285 :
286 482336 : if( psPam->poDefaultRAT != NULL )
287 : {
288 11 : delete psPam->poDefaultRAT;
289 11 : psPam->poDefaultRAT = NULL;
290 : }
291 :
292 482336 : if (psPam->psSavedHistograms != NULL)
293 : {
294 10 : CPLDestroyXMLNode (psPam->psSavedHistograms );
295 10 : psPam->psSavedHistograms = NULL;
296 : }
297 :
298 482336 : CPLFree( psPam );
299 482336 : psPam = NULL;
300 : }
301 623258 : }
302 :
303 : /************************************************************************/
304 : /* XMLInit() */
305 : /************************************************************************/
306 :
307 434 : CPLErr GDALPamRasterBand::XMLInit( CPLXMLNode *psTree, const char *pszUnused )
308 :
309 : {
310 434 : PamInitialize();
311 :
312 : /* -------------------------------------------------------------------- */
313 : /* Apply any dataset level metadata. */
314 : /* -------------------------------------------------------------------- */
315 434 : oMDMD.XMLInit( psTree, TRUE );
316 :
317 : /* -------------------------------------------------------------------- */
318 : /* Collect various other items of metadata. */
319 : /* -------------------------------------------------------------------- */
320 434 : GDALMajorObject::SetDescription( CPLGetXMLValue( psTree, "Description", "" ) );
321 :
322 434 : if( CPLGetXMLValue( psTree, "NoDataValue", NULL ) != NULL )
323 : {
324 : const char *pszLEHex =
325 62 : CPLGetXMLValue( psTree, "NoDataValue.le_hex_equiv", NULL );
326 62 : if( pszLEHex != NULL )
327 : {
328 : int nBytes;
329 11 : GByte *pabyBin = CPLHexToBinary( pszLEHex, &nBytes );
330 11 : if( nBytes == 8 )
331 : {
332 : CPL_LSBPTR64( pabyBin );
333 :
334 11 : GDALPamRasterBand::SetNoDataValue( *((double *) pabyBin) );
335 : }
336 : else
337 : {
338 : GDALPamRasterBand::SetNoDataValue(
339 0 : atof(CPLGetXMLValue( psTree, "NoDataValue", "0" )) );
340 : }
341 11 : CPLFree( pabyBin );
342 : }
343 : else
344 : {
345 : GDALPamRasterBand::SetNoDataValue(
346 51 : atof(CPLGetXMLValue( psTree, "NoDataValue", "0" )) );
347 : }
348 : }
349 :
350 : GDALPamRasterBand::SetOffset(
351 434 : atof(CPLGetXMLValue( psTree, "Offset", "0.0" )) );
352 : GDALPamRasterBand::SetScale(
353 434 : atof(CPLGetXMLValue( psTree, "Scale", "1.0" )) );
354 :
355 434 : GDALPamRasterBand::SetUnitType( CPLGetXMLValue( psTree, "UnitType", NULL));
356 :
357 434 : if( CPLGetXMLValue( psTree, "ColorInterp", NULL ) != NULL )
358 : {
359 221 : const char *pszInterp = CPLGetXMLValue( psTree, "ColorInterp", NULL );
360 : GDALPamRasterBand::SetColorInterpretation(
361 221 : GDALGetColorInterpretationByName(pszInterp));
362 : }
363 :
364 : /* -------------------------------------------------------------------- */
365 : /* Category names. */
366 : /* -------------------------------------------------------------------- */
367 434 : if( CPLGetXMLNode( psTree, "CategoryNames" ) != NULL )
368 : {
369 : CPLXMLNode *psEntry;
370 3 : CPLStringList oCategoryNames;
371 :
372 9 : for( psEntry = CPLGetXMLNode( psTree, "CategoryNames" )->psChild;
373 : psEntry != NULL; psEntry = psEntry->psNext )
374 : {
375 : /* Don't skeep <Category> tag with empty content */
376 6 : if( psEntry->eType != CXT_Element
377 : || !EQUAL(psEntry->pszValue,"Category")
378 : || (psEntry->psChild != NULL && psEntry->psChild->eType != CXT_Text) )
379 0 : continue;
380 :
381 : oCategoryNames.AddString(
382 6 : (psEntry->psChild) ? psEntry->psChild->pszValue : "" );
383 : }
384 :
385 3 : GDALPamRasterBand::SetCategoryNames( oCategoryNames.List() );
386 : }
387 :
388 : /* -------------------------------------------------------------------- */
389 : /* Collect a color table. */
390 : /* -------------------------------------------------------------------- */
391 434 : if( CPLGetXMLNode( psTree, "ColorTable" ) != NULL )
392 : {
393 : CPLXMLNode *psEntry;
394 3 : GDALColorTable oTable;
395 3 : int iEntry = 0;
396 :
397 9 : for( psEntry = CPLGetXMLNode( psTree, "ColorTable" )->psChild;
398 : psEntry != NULL; psEntry = psEntry->psNext )
399 : {
400 : GDALColorEntry sCEntry;
401 :
402 6 : sCEntry.c1 = (short) atoi(CPLGetXMLValue( psEntry, "c1", "0" ));
403 6 : sCEntry.c2 = (short) atoi(CPLGetXMLValue( psEntry, "c2", "0" ));
404 6 : sCEntry.c3 = (short) atoi(CPLGetXMLValue( psEntry, "c3", "0" ));
405 6 : sCEntry.c4 = (short) atoi(CPLGetXMLValue( psEntry, "c4", "255" ));
406 :
407 6 : oTable.SetColorEntry( iEntry++, &sCEntry );
408 : }
409 :
410 3 : GDALPamRasterBand::SetColorTable( &oTable );
411 : }
412 :
413 : /* -------------------------------------------------------------------- */
414 : /* Do we have a complete set of stats? */
415 : /* -------------------------------------------------------------------- */
416 434 : if( CPLGetXMLNode( psTree, "Minimum" ) != NULL
417 : && CPLGetXMLNode( psTree, "Maximum" ) != NULL )
418 : {
419 0 : psPam->bHaveMinMax = TRUE;
420 0 : psPam->dfMin = atof(CPLGetXMLValue(psTree, "Minimum","0"));
421 0 : psPam->dfMax = atof(CPLGetXMLValue(psTree, "Maximum","0"));
422 : }
423 :
424 434 : if( CPLGetXMLNode( psTree, "Mean" ) != NULL
425 : && CPLGetXMLNode( psTree, "StandardDeviation" ) != NULL )
426 : {
427 0 : psPam->bHaveStats = TRUE;
428 0 : psPam->dfMean = atof(CPLGetXMLValue(psTree, "Mean","0"));
429 0 : psPam->dfStdDev = atof(CPLGetXMLValue(psTree,"StandardDeviation","0"));
430 : }
431 :
432 : /* -------------------------------------------------------------------- */
433 : /* Histograms */
434 : /* -------------------------------------------------------------------- */
435 434 : CPLXMLNode *psHist = CPLGetXMLNode( psTree, "Histograms" );
436 434 : if( psHist != NULL )
437 : {
438 3 : CPLXMLNode *psNext = psHist->psNext;
439 3 : psHist->psNext = NULL;
440 :
441 3 : if (psPam->psSavedHistograms != NULL)
442 : {
443 0 : CPLDestroyXMLNode (psPam->psSavedHistograms );
444 0 : psPam->psSavedHistograms = NULL;
445 : }
446 3 : psPam->psSavedHistograms = CPLCloneXMLTree( psHist );
447 3 : psHist->psNext = psNext;
448 : }
449 :
450 : /* -------------------------------------------------------------------- */
451 : /* Raster Attribute Table */
452 : /* -------------------------------------------------------------------- */
453 434 : CPLXMLNode *psRAT = CPLGetXMLNode( psTree, "GDALRasterAttributeTable" );
454 434 : if( psRAT != NULL )
455 : {
456 6 : if( psPam->poDefaultRAT != NULL )
457 : {
458 0 : delete psPam->poDefaultRAT;
459 0 : psPam->poDefaultRAT = NULL;
460 : }
461 6 : psPam->poDefaultRAT = new GDALRasterAttributeTable();
462 6 : psPam->poDefaultRAT->XMLInit( psRAT, "" );
463 : }
464 :
465 434 : return CE_None;
466 : }
467 :
468 : /************************************************************************/
469 : /* CloneInfo() */
470 : /************************************************************************/
471 :
472 927 : CPLErr GDALPamRasterBand::CloneInfo( GDALRasterBand *poSrcBand,
473 : int nCloneFlags )
474 :
475 : {
476 927 : int bOnlyIfMissing = nCloneFlags & GCIF_ONLY_IF_MISSING;
477 : int bSuccess;
478 927 : int nSavedMOFlags = GetMOFlags();
479 :
480 927 : PamInitialize();
481 :
482 : /* -------------------------------------------------------------------- */
483 : /* Supress NotImplemented error messages - mainly needed if PAM */
484 : /* disabled. */
485 : /* -------------------------------------------------------------------- */
486 927 : SetMOFlags( nSavedMOFlags | GMO_IGNORE_UNIMPLEMENTED );
487 :
488 : /* -------------------------------------------------------------------- */
489 : /* Metadata */
490 : /* -------------------------------------------------------------------- */
491 927 : if( nCloneFlags & GCIF_BAND_METADATA )
492 : {
493 927 : if( poSrcBand->GetMetadata() != NULL )
494 : {
495 288 : if( !bOnlyIfMissing
496 192 : || CSLCount(GetMetadata()) != CSLCount(poSrcBand->GetMetadata()) )
497 : {
498 66 : SetMetadata( poSrcBand->GetMetadata() );
499 : }
500 : }
501 : }
502 :
503 : /* -------------------------------------------------------------------- */
504 : /* Band description. */
505 : /* -------------------------------------------------------------------- */
506 927 : if( nCloneFlags & GCIF_BAND_DESCRIPTION )
507 : {
508 927 : if( strlen(poSrcBand->GetDescription()) > 0 )
509 : {
510 6 : if( !bOnlyIfMissing || strlen(GetDescription()) == 0 )
511 1 : GDALPamRasterBand::SetDescription( poSrcBand->GetDescription());
512 : }
513 : }
514 :
515 : /* -------------------------------------------------------------------- */
516 : /* NODATA */
517 : /* -------------------------------------------------------------------- */
518 927 : if( nCloneFlags & GCIF_NODATA )
519 : {
520 927 : double dfNoData = poSrcBand->GetNoDataValue( &bSuccess );
521 :
522 927 : if( bSuccess )
523 : {
524 164 : if( !bOnlyIfMissing
525 82 : || GetNoDataValue( &bSuccess ) != dfNoData
526 : || !bSuccess )
527 7 : GDALPamRasterBand::SetNoDataValue( dfNoData );
528 : }
529 : }
530 :
531 : /* -------------------------------------------------------------------- */
532 : /* Category names */
533 : /* -------------------------------------------------------------------- */
534 927 : if( nCloneFlags & GCIF_CATEGORYNAMES )
535 : {
536 927 : if( poSrcBand->GetCategoryNames() != NULL )
537 : {
538 2 : if( !bOnlyIfMissing || GetCategoryNames() == NULL )
539 1 : GDALPamRasterBand::SetCategoryNames( poSrcBand->GetCategoryNames() );
540 : }
541 : }
542 :
543 : /* -------------------------------------------------------------------- */
544 : /* Offset/scale */
545 : /* -------------------------------------------------------------------- */
546 927 : if( nCloneFlags & GCIF_SCALEOFFSET )
547 : {
548 927 : double dfOffset = poSrcBand->GetOffset( &bSuccess );
549 :
550 927 : if( bSuccess )
551 : {
552 878 : if( !bOnlyIfMissing || GetOffset() != dfOffset )
553 1 : GDALPamRasterBand::SetOffset( dfOffset );
554 : }
555 :
556 927 : double dfScale = poSrcBand->GetScale( &bSuccess );
557 :
558 927 : if( bSuccess )
559 : {
560 878 : if( !bOnlyIfMissing || GetScale() != dfScale )
561 1 : GDALPamRasterBand::SetScale( dfScale );
562 : }
563 : }
564 :
565 : /* -------------------------------------------------------------------- */
566 : /* Unittype. */
567 : /* -------------------------------------------------------------------- */
568 927 : if( nCloneFlags & GCIF_UNITTYPE )
569 : {
570 927 : if( strlen(poSrcBand->GetUnitType()) > 0 )
571 : {
572 45 : if( !bOnlyIfMissing
573 30 : || !EQUAL(GetUnitType(),poSrcBand->GetUnitType()) )
574 : {
575 2 : GDALPamRasterBand::SetUnitType( poSrcBand->GetUnitType() );
576 : }
577 : }
578 : }
579 :
580 : /* -------------------------------------------------------------------- */
581 : /* ColorInterp */
582 : /* -------------------------------------------------------------------- */
583 927 : if( nCloneFlags & GCIF_COLORINTERP )
584 : {
585 927 : if( poSrcBand->GetColorInterpretation() != GCI_Undefined )
586 : {
587 2208 : if( !bOnlyIfMissing
588 736 : || poSrcBand->GetColorInterpretation()
589 736 : != GetColorInterpretation() )
590 : GDALPamRasterBand::SetColorInterpretation(
591 237 : poSrcBand->GetColorInterpretation() );
592 : }
593 : }
594 :
595 : /* -------------------------------------------------------------------- */
596 : /* color table. */
597 : /* -------------------------------------------------------------------- */
598 927 : if( nCloneFlags & GCIF_COLORTABLE )
599 : {
600 927 : if( poSrcBand->GetColorTable() != NULL )
601 : {
602 10 : if( !bOnlyIfMissing || GetColorTable() == NULL )
603 : {
604 : GDALPamRasterBand::SetColorTable(
605 1 : poSrcBand->GetColorTable() );
606 : }
607 : }
608 : }
609 :
610 : /* -------------------------------------------------------------------- */
611 : /* Raster Attribute Table. */
612 : /* -------------------------------------------------------------------- */
613 927 : if( nCloneFlags & GCIF_RAT )
614 : {
615 927 : const GDALRasterAttributeTable *poRAT = poSrcBand->GetDefaultRAT();
616 :
617 927 : if( poRAT != NULL )
618 : {
619 3 : if( !bOnlyIfMissing || GetDefaultRAT() == NULL )
620 : {
621 3 : GDALPamRasterBand::SetDefaultRAT( poRAT );
622 : }
623 : }
624 : }
625 :
626 : /* -------------------------------------------------------------------- */
627 : /* Restore MO flags. */
628 : /* -------------------------------------------------------------------- */
629 927 : SetMOFlags( nSavedMOFlags );
630 :
631 927 : return CE_None;
632 : }
633 :
634 : /************************************************************************/
635 : /* SetMetadata() */
636 : /************************************************************************/
637 :
638 203 : CPLErr GDALPamRasterBand::SetMetadata( char **papszMetadata,
639 : const char *pszDomain )
640 :
641 : {
642 203 : PamInitialize();
643 :
644 203 : if( psPam )
645 203 : psPam->poParentDS->MarkPamDirty();
646 :
647 203 : return GDALRasterBand::SetMetadata( papszMetadata, pszDomain );
648 : }
649 :
650 : /************************************************************************/
651 : /* SetMetadataItem() */
652 : /************************************************************************/
653 :
654 3431 : CPLErr GDALPamRasterBand::SetMetadataItem( const char *pszName,
655 : const char *pszValue,
656 : const char *pszDomain )
657 :
658 : {
659 3431 : PamInitialize();
660 :
661 3431 : if( psPam )
662 3419 : psPam->poParentDS->MarkPamDirty();
663 :
664 3431 : return GDALRasterBand::SetMetadataItem( pszName, pszValue, pszDomain );
665 : }
666 :
667 : /************************************************************************/
668 : /* SetNoDataValue() */
669 : /************************************************************************/
670 :
671 233 : CPLErr GDALPamRasterBand::SetNoDataValue( double dfNewValue )
672 :
673 : {
674 233 : PamInitialize();
675 :
676 233 : if( psPam )
677 : {
678 233 : psPam->bNoDataValueSet = TRUE;
679 233 : psPam->dfNoDataValue = dfNewValue;
680 233 : psPam->poParentDS->MarkPamDirty();
681 233 : return CE_None;
682 : }
683 : else
684 0 : return GDALRasterBand::SetNoDataValue( dfNewValue );
685 : }
686 :
687 : /************************************************************************/
688 : /* GetNoDataValue() */
689 : /************************************************************************/
690 :
691 20644 : double GDALPamRasterBand::GetNoDataValue( int *pbSuccess )
692 :
693 : {
694 20644 : if( psPam != NULL )
695 : {
696 15895 : if( pbSuccess )
697 15833 : *pbSuccess = psPam->bNoDataValueSet;
698 :
699 15895 : return psPam->dfNoDataValue;
700 : }
701 : else
702 4749 : return GDALRasterBand::GetNoDataValue( pbSuccess );
703 : }
704 :
705 : /************************************************************************/
706 : /* GetOffset() */
707 : /************************************************************************/
708 :
709 267829 : double GDALPamRasterBand::GetOffset( int *pbSuccess )
710 :
711 : {
712 267829 : if( psPam )
713 : {
714 267771 : if( pbSuccess != NULL )
715 105 : *pbSuccess = TRUE;
716 :
717 267771 : return psPam->dfOffset;
718 : }
719 : else
720 58 : return GDALRasterBand::GetOffset( pbSuccess );
721 : }
722 :
723 : /************************************************************************/
724 : /* SetOffset() */
725 : /************************************************************************/
726 :
727 585 : CPLErr GDALPamRasterBand::SetOffset( double dfNewOffset )
728 :
729 : {
730 585 : PamInitialize();
731 :
732 585 : if( psPam != NULL )
733 : {
734 585 : if( psPam->dfOffset != dfNewOffset )
735 : {
736 13 : psPam->dfOffset = dfNewOffset;
737 13 : psPam->poParentDS->MarkPamDirty();
738 : }
739 :
740 585 : return CE_None;
741 : }
742 : else
743 0 : return GDALRasterBand::SetOffset( dfNewOffset );
744 : }
745 :
746 : /************************************************************************/
747 : /* GetScale() */
748 : /************************************************************************/
749 :
750 267829 : double GDALPamRasterBand::GetScale( int *pbSuccess )
751 :
752 : {
753 267829 : if( psPam )
754 : {
755 267771 : if( pbSuccess != NULL )
756 267280 : *pbSuccess = TRUE;
757 :
758 267771 : return psPam->dfScale;
759 : }
760 : else
761 58 : return GDALRasterBand::GetScale( pbSuccess );
762 : }
763 :
764 : /************************************************************************/
765 : /* SetScale() */
766 : /************************************************************************/
767 :
768 585 : CPLErr GDALPamRasterBand::SetScale( double dfNewScale )
769 :
770 : {
771 585 : PamInitialize();
772 :
773 585 : if( psPam != NULL )
774 : {
775 585 : if( dfNewScale != psPam->dfScale )
776 : {
777 13 : psPam->dfScale = dfNewScale;
778 13 : psPam->poParentDS->MarkPamDirty();
779 : }
780 585 : return CE_None;
781 : }
782 : else
783 0 : return GDALRasterBand::SetScale( dfNewScale );
784 : }
785 :
786 : /************************************************************************/
787 : /* GetUnitType() */
788 : /************************************************************************/
789 :
790 267305 : const char *GDALPamRasterBand::GetUnitType()
791 :
792 : {
793 267305 : if( psPam != NULL )
794 : {
795 267271 : if( psPam->pszUnitType == NULL )
796 267263 : return "";
797 : else
798 8 : return psPam->pszUnitType;
799 : }
800 : else
801 34 : return GDALRasterBand::GetUnitType();
802 : }
803 :
804 : /************************************************************************/
805 : /* SetUnitType() */
806 : /************************************************************************/
807 :
808 511 : CPLErr GDALPamRasterBand::SetUnitType( const char *pszNewValue )
809 :
810 : {
811 511 : PamInitialize();
812 :
813 511 : if( psPam )
814 : {
815 987 : if( pszNewValue == NULL || pszNewValue[0] == '\0' )
816 : {
817 476 : if (psPam->pszUnitType != NULL)
818 1 : psPam->poParentDS->MarkPamDirty();
819 476 : CPLFree( psPam->pszUnitType );
820 476 : psPam->pszUnitType = NULL;
821 : }
822 : else
823 : {
824 35 : if (psPam->pszUnitType == NULL ||
825 : strcmp(psPam->pszUnitType, pszNewValue) != 0)
826 35 : psPam->poParentDS->MarkPamDirty();
827 35 : CPLFree( psPam->pszUnitType );
828 35 : psPam->pszUnitType = CPLStrdup(pszNewValue);
829 : }
830 :
831 511 : return CE_None;
832 : }
833 : else
834 0 : return GDALRasterBand::SetUnitType( pszNewValue );
835 : }
836 :
837 : /************************************************************************/
838 : /* GetCategoryNames() */
839 : /************************************************************************/
840 :
841 1537 : char **GDALPamRasterBand::GetCategoryNames()
842 :
843 : {
844 1537 : if( psPam )
845 1429 : return psPam->papszCategoryNames;
846 : else
847 108 : return GDALRasterBand::GetCategoryNames();
848 : }
849 :
850 : /************************************************************************/
851 : /* SetCategoryNames() */
852 : /************************************************************************/
853 :
854 23 : CPLErr GDALPamRasterBand::SetCategoryNames( char ** papszNewNames )
855 :
856 : {
857 23 : PamInitialize();
858 :
859 23 : if( psPam )
860 : {
861 23 : CSLDestroy( psPam->papszCategoryNames );
862 23 : psPam->papszCategoryNames = CSLDuplicate( papszNewNames );
863 23 : psPam->poParentDS->MarkPamDirty();
864 23 : return CE_None;
865 : }
866 : else
867 0 : return GDALRasterBand::SetCategoryNames( papszNewNames );
868 :
869 : }
870 :
871 :
872 : /************************************************************************/
873 : /* GetColorTable() */
874 : /************************************************************************/
875 :
876 134 : GDALColorTable *GDALPamRasterBand::GetColorTable()
877 :
878 : {
879 134 : if( psPam )
880 91 : return psPam->poColorTable;
881 : else
882 43 : return GDALRasterBand::GetColorTable();
883 : }
884 :
885 : /************************************************************************/
886 : /* SetColorTable() */
887 : /************************************************************************/
888 :
889 4 : CPLErr GDALPamRasterBand::SetColorTable( GDALColorTable *poTableIn )
890 :
891 : {
892 4 : PamInitialize();
893 :
894 4 : if( psPam )
895 : {
896 4 : if( psPam->poColorTable != NULL )
897 : {
898 0 : delete psPam->poColorTable;
899 0 : psPam->poColorTable = NULL;
900 : }
901 :
902 4 : if( poTableIn )
903 : {
904 4 : psPam->poColorTable = poTableIn->Clone();
905 4 : psPam->eColorInterp = GCI_PaletteIndex;
906 : }
907 :
908 4 : psPam->poParentDS->MarkPamDirty();
909 :
910 4 : return CE_None;
911 : }
912 : else
913 0 : return GDALRasterBand::SetColorTable( poTableIn );
914 :
915 : }
916 :
917 : /************************************************************************/
918 : /* SetColorInterpretation() */
919 : /************************************************************************/
920 :
921 536 : CPLErr GDALPamRasterBand::SetColorInterpretation( GDALColorInterp eInterpIn )
922 :
923 : {
924 536 : PamInitialize();
925 :
926 536 : if( psPam )
927 : {
928 533 : psPam->poParentDS->MarkPamDirty();
929 :
930 533 : psPam->eColorInterp = eInterpIn;
931 :
932 533 : return CE_None;
933 : }
934 : else
935 3 : return GDALRasterBand::SetColorInterpretation( eInterpIn );
936 : }
937 :
938 : /************************************************************************/
939 : /* GetColorInterpretation() */
940 : /************************************************************************/
941 :
942 200 : GDALColorInterp GDALPamRasterBand::GetColorInterpretation()
943 :
944 : {
945 200 : if( psPam )
946 178 : return psPam->eColorInterp;
947 : else
948 22 : return GDALRasterBand::GetColorInterpretation();
949 : }
950 :
951 : /************************************************************************/
952 : /* SetDescription() */
953 : /* */
954 : /* We let the GDALMajorObject hold the description, but we keep */
955 : /* track of whether it has been changed so we know to save it. */
956 : /************************************************************************/
957 :
958 419 : void GDALPamRasterBand::SetDescription( const char *pszDescription )
959 :
960 : {
961 419 : PamInitialize();
962 :
963 419 : if( psPam && strcmp(pszDescription,GetDescription()) != 0 )
964 364 : psPam->poParentDS->MarkPamDirty();
965 :
966 419 : GDALRasterBand::SetDescription( pszDescription );
967 419 : }
968 :
969 : /************************************************************************/
970 : /* PamParseHistogram() */
971 : /************************************************************************/
972 :
973 : int
974 3 : PamParseHistogram( CPLXMLNode *psHistItem,
975 : double *pdfMin, double *pdfMax,
976 : int *pnBuckets, int **ppanHistogram,
977 : int *pbIncludeOutOfRange, int *pbApproxOK )
978 :
979 : {
980 3 : if( psHistItem == NULL )
981 0 : return FALSE;
982 :
983 3 : *pdfMin = atof(CPLGetXMLValue( psHistItem, "HistMin", "0"));
984 3 : *pdfMax = atof(CPLGetXMLValue( psHistItem, "HistMax", "1"));
985 3 : *pnBuckets = atoi(CPLGetXMLValue( psHistItem, "BucketCount","2"));
986 3 : if (*pnBuckets <= 0)
987 0 : return FALSE;
988 :
989 3 : if( ppanHistogram == NULL )
990 0 : return TRUE;
991 :
992 : // Fetch the histogram and use it.
993 : int iBucket;
994 : const char *pszHistCounts = CPLGetXMLValue( psHistItem,
995 3 : "HistCounts", "" );
996 :
997 3 : *ppanHistogram = (int *) VSICalloc(sizeof(int),*pnBuckets);
998 3 : if (*ppanHistogram == NULL)
999 : {
1000 : CPLError(CE_Failure, CPLE_OutOfMemory,
1001 0 : "Cannot allocate memory for %d buckets", *pnBuckets);
1002 0 : return FALSE;
1003 : }
1004 :
1005 517 : for( iBucket = 0; iBucket < *pnBuckets; iBucket++ )
1006 : {
1007 514 : (*ppanHistogram)[iBucket] = atoi(pszHistCounts);
1008 :
1009 : // skip to next number.
1010 1606 : while( *pszHistCounts != '\0' && *pszHistCounts != '|' )
1011 578 : pszHistCounts++;
1012 514 : if( *pszHistCounts == '|' )
1013 511 : pszHistCounts++;
1014 : }
1015 :
1016 3 : return TRUE;
1017 : }
1018 :
1019 : /************************************************************************/
1020 : /* PamFindMatchingHistogram() */
1021 : /************************************************************************/
1022 : CPLXMLNode *
1023 13 : PamFindMatchingHistogram( CPLXMLNode *psSavedHistograms,
1024 : double dfMin, double dfMax, int nBuckets,
1025 : int bIncludeOutOfRange, int bApproxOK )
1026 :
1027 : {
1028 13 : if( psSavedHistograms == NULL )
1029 8 : return NULL;
1030 :
1031 : CPLXMLNode *psXMLHist;
1032 8 : for( psXMLHist = psSavedHistograms->psChild;
1033 : psXMLHist != NULL; psXMLHist = psXMLHist->psNext )
1034 : {
1035 5 : if( psXMLHist->eType != CXT_Element
1036 : || !EQUAL(psXMLHist->pszValue,"HistItem") )
1037 0 : continue;
1038 :
1039 5 : double dfHistMin = atof(CPLGetXMLValue( psXMLHist, "HistMin", "0"));
1040 5 : double dfHistMax = atof(CPLGetXMLValue( psXMLHist, "HistMax", "0"));
1041 :
1042 5 : if( !(ARE_REAL_EQUAL(dfHistMin, dfMin))
1043 : || !(ARE_REAL_EQUAL(dfHistMax, dfMax))
1044 : || atoi(CPLGetXMLValue( psXMLHist,
1045 : "BucketCount","0")) != nBuckets
1046 : || !atoi(CPLGetXMLValue( psXMLHist,
1047 : "IncludeOutOfRange","0")) != !bIncludeOutOfRange
1048 : || (!bApproxOK && atoi(CPLGetXMLValue( psXMLHist,
1049 : "Approximate","0"))) )
1050 :
1051 3 : continue;
1052 :
1053 2 : return psXMLHist;
1054 : }
1055 :
1056 3 : return NULL;
1057 : }
1058 :
1059 : /************************************************************************/
1060 : /* PamHistogramToXMLTree() */
1061 : /************************************************************************/
1062 :
1063 : CPLXMLNode *
1064 12 : PamHistogramToXMLTree( double dfMin, double dfMax,
1065 : int nBuckets, int * panHistogram,
1066 : int bIncludeOutOfRange, int bApprox )
1067 :
1068 : {
1069 12 : char *pszHistCounts = (char *) CPLMalloc(12 * nBuckets + 10);
1070 : int iBucket, iHistOffset;
1071 : CPLXMLNode *psXMLHist;
1072 12 : CPLString oFmt;
1073 :
1074 12 : psXMLHist = CPLCreateXMLNode( NULL, CXT_Element, "HistItem" );
1075 :
1076 : CPLSetXMLValue( psXMLHist, "HistMin",
1077 12 : oFmt.Printf( "%.16g", dfMin ));
1078 : CPLSetXMLValue( psXMLHist, "HistMax",
1079 12 : oFmt.Printf( "%.16g", dfMax ));
1080 : CPLSetXMLValue( psXMLHist, "BucketCount",
1081 12 : oFmt.Printf( "%d", nBuckets ));
1082 : CPLSetXMLValue( psXMLHist, "IncludeOutOfRange",
1083 12 : oFmt.Printf( "%d", bIncludeOutOfRange ));
1084 : CPLSetXMLValue( psXMLHist, "Approximate",
1085 12 : oFmt.Printf( "%d", bApprox ));
1086 :
1087 12 : iHistOffset = 0;
1088 12 : pszHistCounts[0] = '\0';
1089 1574 : for( iBucket = 0; iBucket < nBuckets; iBucket++ )
1090 : {
1091 1562 : sprintf( pszHistCounts + iHistOffset, "%d", panHistogram[iBucket] );
1092 1562 : if( iBucket < nBuckets-1 )
1093 1551 : strcat( pszHistCounts + iHistOffset, "|" );
1094 1562 : iHistOffset += strlen(pszHistCounts+iHistOffset);
1095 : }
1096 :
1097 12 : CPLSetXMLValue( psXMLHist, "HistCounts", pszHistCounts );
1098 12 : CPLFree( pszHistCounts );
1099 :
1100 12 : return psXMLHist;
1101 : }
1102 :
1103 : /************************************************************************/
1104 : /* GetHistogram() */
1105 : /************************************************************************/
1106 :
1107 9 : CPLErr GDALPamRasterBand::GetHistogram( double dfMin, double dfMax,
1108 : int nBuckets, int * panHistogram,
1109 : int bIncludeOutOfRange, int bApproxOK,
1110 : GDALProgressFunc pfnProgress,
1111 : void *pProgressData )
1112 :
1113 : {
1114 9 : PamInitialize();
1115 :
1116 9 : if( psPam == NULL )
1117 : return GDALRasterBand::GetHistogram( dfMin, dfMax,
1118 : nBuckets, panHistogram,
1119 : bIncludeOutOfRange, bApproxOK,
1120 0 : pfnProgress, pProgressData );
1121 :
1122 : /* -------------------------------------------------------------------- */
1123 : /* Check if we have a matching histogram. */
1124 : /* -------------------------------------------------------------------- */
1125 : CPLXMLNode *psHistItem;
1126 :
1127 : psHistItem = PamFindMatchingHistogram( psPam->psSavedHistograms,
1128 : dfMin, dfMax, nBuckets,
1129 9 : bIncludeOutOfRange, bApproxOK );
1130 9 : if( psHistItem != NULL )
1131 : {
1132 1 : int *panTempHist = NULL;
1133 :
1134 1 : if( PamParseHistogram( psHistItem, &dfMin, &dfMax, &nBuckets,
1135 : &panTempHist,
1136 : &bIncludeOutOfRange, &bApproxOK ) )
1137 : {
1138 1 : memcpy( panHistogram, panTempHist, sizeof(int) * nBuckets );
1139 1 : CPLFree( panTempHist );
1140 1 : return CE_None;
1141 : }
1142 : }
1143 :
1144 : /* -------------------------------------------------------------------- */
1145 : /* We don't have an existing histogram matching the request, so */
1146 : /* generate one manually. */
1147 : /* -------------------------------------------------------------------- */
1148 : CPLErr eErr;
1149 :
1150 : eErr = GDALRasterBand::GetHistogram( dfMin, dfMax,
1151 : nBuckets, panHistogram,
1152 : bIncludeOutOfRange, bApproxOK,
1153 8 : pfnProgress, pProgressData );
1154 :
1155 : /* -------------------------------------------------------------------- */
1156 : /* Save an XML description of this histogram. */
1157 : /* -------------------------------------------------------------------- */
1158 8 : if( eErr == CE_None )
1159 : {
1160 : CPLXMLNode *psXMLHist;
1161 :
1162 : psXMLHist = PamHistogramToXMLTree( dfMin, dfMax, nBuckets,
1163 : panHistogram,
1164 8 : bIncludeOutOfRange, bApproxOK );
1165 8 : if( psXMLHist != NULL )
1166 : {
1167 8 : psPam->poParentDS->MarkPamDirty();
1168 :
1169 8 : if( psPam->psSavedHistograms == NULL )
1170 : psPam->psSavedHistograms = CPLCreateXMLNode( NULL, CXT_Element,
1171 6 : "Histograms" );
1172 :
1173 8 : CPLAddXMLChild( psPam->psSavedHistograms, psXMLHist );
1174 : }
1175 : }
1176 :
1177 8 : return eErr;
1178 : }
1179 :
1180 : /************************************************************************/
1181 : /* SetDefaultHistogram() */
1182 : /************************************************************************/
1183 :
1184 1 : CPLErr GDALPamRasterBand::SetDefaultHistogram( double dfMin, double dfMax,
1185 : int nBuckets, int *panHistogram)
1186 :
1187 : {
1188 : CPLXMLNode *psNode;
1189 :
1190 1 : PamInitialize();
1191 :
1192 1 : if( psPam == NULL )
1193 : return GDALRasterBand::SetDefaultHistogram( dfMin, dfMax,
1194 0 : nBuckets, panHistogram );
1195 :
1196 : /* -------------------------------------------------------------------- */
1197 : /* Do we have a matching histogram we should replace? */
1198 : /* -------------------------------------------------------------------- */
1199 : psNode = PamFindMatchingHistogram( psPam->psSavedHistograms,
1200 : dfMin, dfMax, nBuckets,
1201 1 : TRUE, TRUE );
1202 1 : if( psNode != NULL )
1203 : {
1204 : /* blow this one away */
1205 0 : CPLRemoveXMLChild( psPam->psSavedHistograms, psNode );
1206 0 : CPLDestroyXMLNode( psNode );
1207 : }
1208 :
1209 : /* -------------------------------------------------------------------- */
1210 : /* Translate into a histogram XML tree. */
1211 : /* -------------------------------------------------------------------- */
1212 : CPLXMLNode *psHistItem;
1213 :
1214 : psHistItem = PamHistogramToXMLTree( dfMin, dfMax, nBuckets,
1215 1 : panHistogram, TRUE, FALSE );
1216 :
1217 : /* -------------------------------------------------------------------- */
1218 : /* Insert our new default histogram at the front of the */
1219 : /* histogram list so that it will be the default histogram. */
1220 : /* -------------------------------------------------------------------- */
1221 1 : psPam->poParentDS->MarkPamDirty();
1222 :
1223 1 : if( psPam->psSavedHistograms == NULL )
1224 : psPam->psSavedHistograms = CPLCreateXMLNode( NULL, CXT_Element,
1225 1 : "Histograms" );
1226 :
1227 1 : psHistItem->psNext = psPam->psSavedHistograms->psChild;
1228 1 : psPam->psSavedHistograms->psChild = psHistItem;
1229 :
1230 1 : return CE_None;
1231 : }
1232 :
1233 : /************************************************************************/
1234 : /* GetDefaultHistogram() */
1235 : /************************************************************************/
1236 :
1237 : CPLErr
1238 12 : GDALPamRasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax,
1239 : int *pnBuckets, int **ppanHistogram,
1240 : int bForce,
1241 : GDALProgressFunc pfnProgress,
1242 : void *pProgressData )
1243 :
1244 : {
1245 12 : if( psPam && psPam->psSavedHistograms != NULL )
1246 : {
1247 : CPLXMLNode *psXMLHist;
1248 :
1249 2 : for( psXMLHist = psPam->psSavedHistograms->psChild;
1250 : psXMLHist != NULL; psXMLHist = psXMLHist->psNext )
1251 : {
1252 : int bApprox, bIncludeOutOfRange;
1253 :
1254 1 : if( psXMLHist->eType != CXT_Element
1255 : || !EQUAL(psXMLHist->pszValue,"HistItem") )
1256 0 : continue;
1257 :
1258 1 : if( PamParseHistogram( psXMLHist, pdfMin, pdfMax, pnBuckets,
1259 : ppanHistogram, &bIncludeOutOfRange,
1260 : &bApprox ) )
1261 1 : return CE_None;
1262 : else
1263 0 : return CE_Failure;
1264 : }
1265 : }
1266 :
1267 : return GDALRasterBand::GetDefaultHistogram( pdfMin, pdfMax, pnBuckets,
1268 : ppanHistogram, bForce,
1269 11 : pfnProgress, pProgressData );
1270 : }
1271 :
1272 : /************************************************************************/
1273 : /* GetDefaultRAT() */
1274 : /************************************************************************/
1275 :
1276 815 : const GDALRasterAttributeTable *GDALPamRasterBand::GetDefaultRAT()
1277 :
1278 : {
1279 815 : PamInitialize();
1280 :
1281 815 : if( psPam == NULL )
1282 111 : return GDALRasterBand::GetDefaultRAT();
1283 :
1284 704 : return psPam->poDefaultRAT;
1285 : }
1286 :
1287 : /************************************************************************/
1288 : /* SetDefaultRAT() */
1289 : /************************************************************************/
1290 :
1291 5 : CPLErr GDALPamRasterBand::SetDefaultRAT( const GDALRasterAttributeTable *poRAT)
1292 :
1293 : {
1294 5 : PamInitialize();
1295 :
1296 5 : if( psPam == NULL )
1297 0 : return GDALRasterBand::SetDefaultRAT( poRAT );
1298 :
1299 5 : psPam->poParentDS->MarkPamDirty();
1300 :
1301 5 : if( psPam->poDefaultRAT != NULL )
1302 : {
1303 0 : delete psPam->poDefaultRAT;
1304 0 : psPam->poDefaultRAT = NULL;
1305 : }
1306 :
1307 5 : if( poRAT == NULL )
1308 0 : psPam->poDefaultRAT = NULL;
1309 : else
1310 5 : psPam->poDefaultRAT = poRAT->Clone();
1311 :
1312 5 : return CE_None;
1313 : }
1314 :
|