1 : /******************************************************************************
2 : * $Id: gdalpamrasterband.cpp 22858 2011-08-02 18:18:19Z 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 22858 2011-08-02 18:18:19Z rouault $");
37 :
38 : /************************************************************************/
39 : /* GDALPamRasterBand() */
40 : /************************************************************************/
41 :
42 621107 : GDALPamRasterBand::GDALPamRasterBand()
43 :
44 : {
45 621107 : psPam = NULL;
46 621107 : SetMOFlags( GetMOFlags() | GMO_PAM_CLASS );
47 621107 : }
48 :
49 : /************************************************************************/
50 : /* ~GDALPamRasterBand() */
51 : /************************************************************************/
52 :
53 621107 : GDALPamRasterBand::~GDALPamRasterBand()
54 :
55 : {
56 621107 : PamClear();
57 621107 : }
58 :
59 : /************************************************************************/
60 : /* SerializeToXML() */
61 : /************************************************************************/
62 :
63 1172 : CPLXMLNode *GDALPamRasterBand::SerializeToXML( const char *pszUnused )
64 :
65 : {
66 1172 : if( psPam == NULL )
67 19 : return NULL;
68 :
69 : /* -------------------------------------------------------------------- */
70 : /* Setup root node and attributes. */
71 : /* -------------------------------------------------------------------- */
72 1153 : CPLString oFmt;
73 :
74 : CPLXMLNode *psTree;
75 :
76 1153 : psTree = CPLCreateXMLNode( NULL, CXT_Element, "PAMRasterBand" );
77 :
78 1153 : if( GetBand() > 0 )
79 1153 : CPLSetXMLValue( psTree, "#band", oFmt.Printf( "%d", GetBand() ) );
80 :
81 : /* -------------------------------------------------------------------- */
82 : /* Serialize information of interest. */
83 : /* -------------------------------------------------------------------- */
84 1153 : if( strlen(GetDescription()) > 0 )
85 92 : CPLSetXMLValue( psTree, "Description", GetDescription() );
86 :
87 1153 : if( psPam->bNoDataValueSet )
88 : {
89 70 : if (CPLIsNan(psPam->dfNoDataValue))
90 1 : CPLSetXMLValue( psTree, "NoDataValue", "nan" );
91 : else
92 : CPLSetXMLValue( psTree, "NoDataValue",
93 69 : oFmt.Printf( "%.14E", psPam->dfNoDataValue ) );
94 :
95 : /* hex encode real floating point values */
96 70 : if( psPam->dfNoDataValue != floor(psPam->dfNoDataValue)
97 : || psPam->dfNoDataValue != atof(oFmt) )
98 : {
99 : double dfNoDataLittleEndian;
100 :
101 13 : dfNoDataLittleEndian = psPam->dfNoDataValue;
102 : CPL_LSBPTR64( &dfNoDataLittleEndian );
103 :
104 : char *pszHexEncoding =
105 13 : CPLBinaryToHex( 8, (GByte *) &dfNoDataLittleEndian );
106 13 : CPLSetXMLValue( psTree, "NoDataValue.#le_hex_equiv",pszHexEncoding);
107 13 : CPLFree( pszHexEncoding );
108 : }
109 : }
110 :
111 1153 : if( psPam->pszUnitType != NULL )
112 3 : CPLSetXMLValue( psTree, "UnitType", psPam->pszUnitType );
113 :
114 1153 : if( psPam->dfOffset != 0.0 )
115 : CPLSetXMLValue( psTree, "Offset",
116 2 : oFmt.Printf( "%.16g", psPam->dfOffset ) );
117 :
118 1153 : if( psPam->dfScale != 1.0 )
119 : CPLSetXMLValue( psTree, "Scale",
120 2 : oFmt.Printf( "%.16g", psPam->dfScale ) );
121 :
122 1153 : if( psPam->eColorInterp != GCI_Undefined )
123 : CPLSetXMLValue( psTree, "ColorInterp",
124 292 : GDALGetColorInterpretationName( psPam->eColorInterp ));
125 :
126 : /* -------------------------------------------------------------------- */
127 : /* Category names. */
128 : /* -------------------------------------------------------------------- */
129 1153 : 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 1153 : 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 1153 : 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 1153 : 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 1153 : if( psPam->psSavedHistograms != NULL )
203 8 : CPLAddXMLChild( psTree, CPLCloneXMLTree( psPam->psSavedHistograms ) );
204 :
205 : /* -------------------------------------------------------------------- */
206 : /* Raster Attribute Table */
207 : /* -------------------------------------------------------------------- */
208 1153 : if( psPam->poDefaultRAT != NULL )
209 4 : CPLAddXMLChild( psTree, psPam->poDefaultRAT->Serialize() );
210 :
211 : /* -------------------------------------------------------------------- */
212 : /* Metadata. */
213 : /* -------------------------------------------------------------------- */
214 : CPLXMLNode *psMD;
215 :
216 1153 : psMD = oMDMD.Serialize();
217 1153 : if( psMD != NULL )
218 : {
219 304 : if( psMD->psChild == NULL )
220 3 : CPLDestroyXMLNode( psMD );
221 : else
222 301 : CPLAddXMLChild( psTree, psMD );
223 : }
224 :
225 : /* -------------------------------------------------------------------- */
226 : /* We don't want to return anything if we had no metadata to */
227 : /* attach. */
228 : /* -------------------------------------------------------------------- */
229 1153 : if( psTree->psChild == NULL || psTree->psChild->psNext == NULL )
230 : {
231 531 : CPLDestroyXMLNode( psTree );
232 531 : psTree = NULL;
233 : }
234 :
235 1153 : return psTree;
236 : }
237 :
238 : /************************************************************************/
239 : /* PamInitialize() */
240 : /************************************************************************/
241 :
242 487784 : void GDALPamRasterBand::PamInitialize()
243 :
244 : {
245 487784 : if( psPam )
246 5322 : return;
247 :
248 482462 : GDALPamDataset *poParentDS = (GDALPamDataset *) GetDataset();
249 :
250 482462 : if( poParentDS == NULL || !(poParentDS->GetMOFlags() & GMO_PAM_CLASS) )
251 82 : return;
252 :
253 482380 : poParentDS->PamInitialize();
254 482380 : if( poParentDS->psPam == NULL )
255 1072 : return;
256 :
257 : // Often (always?) initializing our parent will have initialized us.
258 481308 : if( psPam != NULL )
259 454 : return;
260 :
261 : psPam = (GDALRasterBandPamInfo *)
262 480854 : CPLCalloc(sizeof(GDALRasterBandPamInfo),1);
263 :
264 480854 : psPam->dfScale = 1.0;
265 480854 : psPam->poParentDS = poParentDS;
266 480854 : psPam->dfNoDataValue = -1e10;
267 480854 : psPam->poDefaultRAT = NULL;
268 : }
269 :
270 : /************************************************************************/
271 : /* PamClear() */
272 : /************************************************************************/
273 :
274 621107 : void GDALPamRasterBand::PamClear()
275 :
276 : {
277 621107 : if( psPam )
278 : {
279 480854 : if( psPam->poColorTable )
280 4 : delete psPam->poColorTable;
281 480854 : psPam->poColorTable = NULL;
282 :
283 480854 : CPLFree( psPam->pszUnitType );
284 480854 : CSLDestroy( psPam->papszCategoryNames );
285 :
286 480854 : if( psPam->poDefaultRAT != NULL )
287 : {
288 11 : delete psPam->poDefaultRAT;
289 11 : psPam->poDefaultRAT = NULL;
290 : }
291 :
292 480854 : if (psPam->psSavedHistograms != NULL)
293 : {
294 9 : CPLDestroyXMLNode (psPam->psSavedHistograms );
295 9 : psPam->psSavedHistograms = NULL;
296 : }
297 :
298 480854 : CPLFree( psPam );
299 480854 : psPam = NULL;
300 : }
301 621107 : }
302 :
303 : /************************************************************************/
304 : /* XMLInit() */
305 : /************************************************************************/
306 :
307 406 : CPLErr GDALPamRasterBand::XMLInit( CPLXMLNode *psTree, const char *pszUnused )
308 :
309 : {
310 406 : PamInitialize();
311 :
312 : /* -------------------------------------------------------------------- */
313 : /* Apply any dataset level metadata. */
314 : /* -------------------------------------------------------------------- */
315 406 : oMDMD.XMLInit( psTree, TRUE );
316 :
317 : /* -------------------------------------------------------------------- */
318 : /* Collect various other items of metadata. */
319 : /* -------------------------------------------------------------------- */
320 406 : GDALMajorObject::SetDescription( CPLGetXMLValue( psTree, "Description", "" ) );
321 :
322 406 : if( CPLGetXMLValue( psTree, "NoDataValue", NULL ) != NULL )
323 : {
324 : const char *pszLEHex =
325 56 : CPLGetXMLValue( psTree, "NoDataValue.le_hex_equiv", NULL );
326 56 : 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 45 : atof(CPLGetXMLValue( psTree, "NoDataValue", "0" )) );
347 : }
348 : }
349 :
350 : GDALPamRasterBand::SetOffset(
351 406 : atof(CPLGetXMLValue( psTree, "Offset", "0.0" )) );
352 : GDALPamRasterBand::SetScale(
353 406 : atof(CPLGetXMLValue( psTree, "Scale", "1.0" )) );
354 :
355 406 : GDALPamRasterBand::SetUnitType( CPLGetXMLValue( psTree, "UnitType", NULL));
356 :
357 406 : if( CPLGetXMLValue( psTree, "ColorInterp", NULL ) != NULL )
358 : {
359 220 : const char *pszInterp = CPLGetXMLValue( psTree, "ColorInterp", NULL );
360 : GDALPamRasterBand::SetColorInterpretation(
361 220 : GDALGetColorInterpretationByName(pszInterp));
362 : }
363 :
364 : /* -------------------------------------------------------------------- */
365 : /* Category names. */
366 : /* -------------------------------------------------------------------- */
367 406 : 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 406 : 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 406 : 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 406 : 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 406 : CPLXMLNode *psHist = CPLGetXMLNode( psTree, "Histograms" );
436 406 : if( psHist != NULL )
437 : {
438 3 : CPLXMLNode *psNext = psHist->psNext;
439 3 : psHist->psNext = NULL;
440 :
441 3 : psPam->psSavedHistograms = CPLCloneXMLTree( psHist );
442 3 : psHist->psNext = psNext;
443 : }
444 :
445 : /* -------------------------------------------------------------------- */
446 : /* Raster Attribute Table */
447 : /* -------------------------------------------------------------------- */
448 406 : CPLXMLNode *psRAT = CPLGetXMLNode( psTree, "GDALRasterAttributeTable" );
449 406 : if( psRAT != NULL )
450 : {
451 6 : psPam->poDefaultRAT = new GDALRasterAttributeTable();
452 6 : psPam->poDefaultRAT->XMLInit( psRAT, "" );
453 : }
454 :
455 406 : return CE_None;
456 : }
457 :
458 : /************************************************************************/
459 : /* CloneInfo() */
460 : /************************************************************************/
461 :
462 778 : CPLErr GDALPamRasterBand::CloneInfo( GDALRasterBand *poSrcBand,
463 : int nCloneFlags )
464 :
465 : {
466 778 : int bOnlyIfMissing = nCloneFlags & GCIF_ONLY_IF_MISSING;
467 : int bSuccess;
468 778 : int nSavedMOFlags = GetMOFlags();
469 :
470 778 : PamInitialize();
471 :
472 : /* -------------------------------------------------------------------- */
473 : /* Supress NotImplemented error messages - mainly needed if PAM */
474 : /* disabled. */
475 : /* -------------------------------------------------------------------- */
476 778 : SetMOFlags( nSavedMOFlags | GMO_IGNORE_UNIMPLEMENTED );
477 :
478 : /* -------------------------------------------------------------------- */
479 : /* Metadata */
480 : /* -------------------------------------------------------------------- */
481 778 : if( nCloneFlags & GCIF_BAND_METADATA )
482 : {
483 778 : if( poSrcBand->GetMetadata() != NULL )
484 : {
485 213 : if( !bOnlyIfMissing
486 142 : || CSLCount(GetMetadata()) != CSLCount(poSrcBand->GetMetadata()) )
487 : {
488 41 : SetMetadata( poSrcBand->GetMetadata() );
489 : }
490 : }
491 : }
492 :
493 : /* -------------------------------------------------------------------- */
494 : /* Band description. */
495 : /* -------------------------------------------------------------------- */
496 778 : if( nCloneFlags & GCIF_BAND_DESCRIPTION )
497 : {
498 778 : if( strlen(poSrcBand->GetDescription()) > 0 )
499 : {
500 6 : if( !bOnlyIfMissing || strlen(GetDescription()) == 0 )
501 1 : GDALPamRasterBand::SetDescription( poSrcBand->GetDescription());
502 : }
503 : }
504 :
505 : /* -------------------------------------------------------------------- */
506 : /* NODATA */
507 : /* -------------------------------------------------------------------- */
508 778 : if( nCloneFlags & GCIF_NODATA )
509 : {
510 778 : double dfNoData = poSrcBand->GetNoDataValue( &bSuccess );
511 :
512 778 : if( bSuccess )
513 : {
514 142 : if( !bOnlyIfMissing
515 71 : || GetNoDataValue( &bSuccess ) != dfNoData
516 : || !bSuccess )
517 5 : GDALPamRasterBand::SetNoDataValue( dfNoData );
518 : }
519 : }
520 :
521 : /* -------------------------------------------------------------------- */
522 : /* Category names */
523 : /* -------------------------------------------------------------------- */
524 778 : if( nCloneFlags & GCIF_CATEGORYNAMES )
525 : {
526 778 : if( poSrcBand->GetCategoryNames() != NULL )
527 : {
528 2 : if( !bOnlyIfMissing || GetCategoryNames() == NULL )
529 1 : GDALPamRasterBand::SetCategoryNames( poSrcBand->GetCategoryNames() );
530 : }
531 : }
532 :
533 : /* -------------------------------------------------------------------- */
534 : /* Offset/scale */
535 : /* -------------------------------------------------------------------- */
536 778 : if( nCloneFlags & GCIF_SCALEOFFSET )
537 : {
538 778 : double dfOffset = poSrcBand->GetOffset( &bSuccess );
539 :
540 778 : if( bSuccess )
541 : {
542 743 : if( !bOnlyIfMissing || GetOffset() != dfOffset )
543 1 : GDALPamRasterBand::SetOffset( dfOffset );
544 : }
545 :
546 778 : double dfScale = poSrcBand->GetScale( &bSuccess );
547 :
548 778 : if( bSuccess )
549 : {
550 743 : if( !bOnlyIfMissing || GetScale() != dfScale )
551 1 : GDALPamRasterBand::SetScale( dfScale );
552 : }
553 : }
554 :
555 : /* -------------------------------------------------------------------- */
556 : /* Unittype. */
557 : /* -------------------------------------------------------------------- */
558 778 : if( nCloneFlags & GCIF_UNITTYPE )
559 : {
560 778 : if( strlen(poSrcBand->GetUnitType()) > 0 )
561 : {
562 45 : if( !bOnlyIfMissing
563 30 : || !EQUAL(GetUnitType(),poSrcBand->GetUnitType()) )
564 : {
565 2 : GDALPamRasterBand::SetUnitType( poSrcBand->GetUnitType() );
566 : }
567 : }
568 : }
569 :
570 : /* -------------------------------------------------------------------- */
571 : /* ColorInterp */
572 : /* -------------------------------------------------------------------- */
573 778 : if( nCloneFlags & GCIF_COLORINTERP )
574 : {
575 778 : if( poSrcBand->GetColorInterpretation() != GCI_Undefined )
576 : {
577 1938 : if( !bOnlyIfMissing
578 646 : || poSrcBand->GetColorInterpretation()
579 646 : != GetColorInterpretation() )
580 : GDALPamRasterBand::SetColorInterpretation(
581 203 : poSrcBand->GetColorInterpretation() );
582 : }
583 : }
584 :
585 : /* -------------------------------------------------------------------- */
586 : /* color table. */
587 : /* -------------------------------------------------------------------- */
588 778 : if( nCloneFlags & GCIF_COLORTABLE )
589 : {
590 778 : if( poSrcBand->GetColorTable() != NULL )
591 : {
592 10 : if( !bOnlyIfMissing || GetColorTable() == NULL )
593 : {
594 : GDALPamRasterBand::SetColorTable(
595 1 : poSrcBand->GetColorTable() );
596 : }
597 : }
598 : }
599 :
600 : /* -------------------------------------------------------------------- */
601 : /* Raster Attribute Table. */
602 : /* -------------------------------------------------------------------- */
603 778 : if( nCloneFlags & GCIF_RAT )
604 : {
605 778 : const GDALRasterAttributeTable *poRAT = poSrcBand->GetDefaultRAT();
606 :
607 778 : if( poRAT != NULL )
608 : {
609 3 : if( !bOnlyIfMissing || GetDefaultRAT() == NULL )
610 : {
611 3 : GDALPamRasterBand::SetDefaultRAT( poRAT );
612 : }
613 : }
614 : }
615 :
616 : /* -------------------------------------------------------------------- */
617 : /* Restore MO flags. */
618 : /* -------------------------------------------------------------------- */
619 778 : SetMOFlags( nSavedMOFlags );
620 :
621 778 : return CE_None;
622 : }
623 :
624 : /************************************************************************/
625 : /* SetMetadata() */
626 : /************************************************************************/
627 :
628 171 : CPLErr GDALPamRasterBand::SetMetadata( char **papszMetadata,
629 : const char *pszDomain )
630 :
631 : {
632 171 : PamInitialize();
633 :
634 171 : if( psPam )
635 171 : psPam->poParentDS->MarkPamDirty();
636 :
637 171 : return GDALRasterBand::SetMetadata( papszMetadata, pszDomain );
638 : }
639 :
640 : /************************************************************************/
641 : /* SetMetadataItem() */
642 : /************************************************************************/
643 :
644 3077 : CPLErr GDALPamRasterBand::SetMetadataItem( const char *pszName,
645 : const char *pszValue,
646 : const char *pszDomain )
647 :
648 : {
649 3077 : PamInitialize();
650 :
651 3077 : if( psPam )
652 1999 : psPam->poParentDS->MarkPamDirty();
653 :
654 3077 : return GDALRasterBand::SetMetadataItem( pszName, pszValue, pszDomain );
655 : }
656 :
657 : /************************************************************************/
658 : /* SetNoDataValue() */
659 : /************************************************************************/
660 :
661 179 : CPLErr GDALPamRasterBand::SetNoDataValue( double dfNewValue )
662 :
663 : {
664 179 : PamInitialize();
665 :
666 179 : if( psPam )
667 : {
668 179 : psPam->bNoDataValueSet = TRUE;
669 179 : psPam->dfNoDataValue = dfNewValue;
670 179 : psPam->poParentDS->MarkPamDirty();
671 179 : return CE_None;
672 : }
673 : else
674 0 : return GDALRasterBand::SetNoDataValue( dfNewValue );
675 : }
676 :
677 : /************************************************************************/
678 : /* GetNoDataValue() */
679 : /************************************************************************/
680 :
681 18751 : double GDALPamRasterBand::GetNoDataValue( int *pbSuccess )
682 :
683 : {
684 18751 : if( psPam != NULL )
685 : {
686 14095 : if( pbSuccess )
687 14041 : *pbSuccess = psPam->bNoDataValueSet;
688 :
689 14095 : return psPam->dfNoDataValue;
690 : }
691 : else
692 4656 : return GDALRasterBand::GetNoDataValue( pbSuccess );
693 : }
694 :
695 : /************************************************************************/
696 : /* GetOffset() */
697 : /************************************************************************/
698 :
699 267403 : double GDALPamRasterBand::GetOffset( int *pbSuccess )
700 :
701 : {
702 267403 : if( psPam )
703 : {
704 267368 : if( pbSuccess != NULL )
705 86 : *pbSuccess = TRUE;
706 :
707 267368 : return psPam->dfOffset;
708 : }
709 : else
710 35 : return GDALRasterBand::GetOffset( pbSuccess );
711 : }
712 :
713 : /************************************************************************/
714 : /* SetOffset() */
715 : /************************************************************************/
716 :
717 556 : CPLErr GDALPamRasterBand::SetOffset( double dfNewOffset )
718 :
719 : {
720 556 : PamInitialize();
721 :
722 556 : if( psPam != NULL )
723 : {
724 556 : if( psPam->dfOffset != dfNewOffset )
725 : {
726 13 : psPam->dfOffset = dfNewOffset;
727 13 : psPam->poParentDS->MarkPamDirty();
728 : }
729 :
730 556 : return CE_None;
731 : }
732 : else
733 0 : return GDALRasterBand::SetOffset( dfNewOffset );
734 : }
735 :
736 : /************************************************************************/
737 : /* GetScale() */
738 : /************************************************************************/
739 :
740 267403 : double GDALPamRasterBand::GetScale( int *pbSuccess )
741 :
742 : {
743 267403 : if( psPam )
744 : {
745 267368 : if( pbSuccess != NULL )
746 266984 : *pbSuccess = TRUE;
747 :
748 267368 : return psPam->dfScale;
749 : }
750 : else
751 35 : return GDALRasterBand::GetScale( pbSuccess );
752 : }
753 :
754 : /************************************************************************/
755 : /* SetScale() */
756 : /************************************************************************/
757 :
758 556 : CPLErr GDALPamRasterBand::SetScale( double dfNewScale )
759 :
760 : {
761 556 : PamInitialize();
762 :
763 556 : if( psPam != NULL )
764 : {
765 556 : if( dfNewScale != psPam->dfScale )
766 : {
767 13 : psPam->dfScale = dfNewScale;
768 13 : psPam->poParentDS->MarkPamDirty();
769 : }
770 556 : return CE_None;
771 : }
772 : else
773 0 : return GDALRasterBand::SetScale( dfNewScale );
774 : }
775 :
776 : /************************************************************************/
777 : /* GetUnitType() */
778 : /************************************************************************/
779 :
780 266966 : const char *GDALPamRasterBand::GetUnitType()
781 :
782 : {
783 266966 : if( psPam != NULL )
784 : {
785 266950 : if( psPam->pszUnitType == NULL )
786 266942 : return "";
787 : else
788 8 : return psPam->pszUnitType;
789 : }
790 : else
791 16 : return GDALRasterBand::GetUnitType();
792 : }
793 :
794 : /************************************************************************/
795 : /* SetUnitType() */
796 : /************************************************************************/
797 :
798 482 : CPLErr GDALPamRasterBand::SetUnitType( const char *pszNewValue )
799 :
800 : {
801 482 : PamInitialize();
802 :
803 482 : if( psPam )
804 : {
805 929 : if( pszNewValue == NULL || pszNewValue[0] == '\0' )
806 : {
807 447 : if (psPam->pszUnitType != NULL)
808 1 : psPam->poParentDS->MarkPamDirty();
809 447 : CPLFree( psPam->pszUnitType );
810 447 : psPam->pszUnitType = NULL;
811 : }
812 : else
813 : {
814 35 : if (psPam->pszUnitType == NULL ||
815 : strcmp(psPam->pszUnitType, pszNewValue) != 0)
816 35 : psPam->poParentDS->MarkPamDirty();
817 35 : CPLFree( psPam->pszUnitType );
818 35 : psPam->pszUnitType = CPLStrdup(pszNewValue);
819 : }
820 :
821 482 : return CE_None;
822 : }
823 : else
824 0 : return GDALRasterBand::SetUnitType( pszNewValue );
825 : }
826 :
827 : /************************************************************************/
828 : /* GetCategoryNames() */
829 : /************************************************************************/
830 :
831 1364 : char **GDALPamRasterBand::GetCategoryNames()
832 :
833 : {
834 1364 : if( psPam )
835 1271 : return psPam->papszCategoryNames;
836 : else
837 93 : return GDALRasterBand::GetCategoryNames();
838 : }
839 :
840 : /************************************************************************/
841 : /* SetCategoryNames() */
842 : /************************************************************************/
843 :
844 23 : CPLErr GDALPamRasterBand::SetCategoryNames( char ** papszNewNames )
845 :
846 : {
847 23 : PamInitialize();
848 :
849 23 : if( psPam )
850 : {
851 23 : CSLDestroy( psPam->papszCategoryNames );
852 23 : psPam->papszCategoryNames = CSLDuplicate( papszNewNames );
853 23 : psPam->poParentDS->MarkPamDirty();
854 23 : return CE_None;
855 : }
856 : else
857 0 : return GDALRasterBand::SetCategoryNames( papszNewNames );
858 :
859 : }
860 :
861 :
862 : /************************************************************************/
863 : /* GetColorTable() */
864 : /************************************************************************/
865 :
866 81 : GDALColorTable *GDALPamRasterBand::GetColorTable()
867 :
868 : {
869 81 : if( psPam )
870 60 : return psPam->poColorTable;
871 : else
872 21 : return GDALRasterBand::GetColorTable();
873 : }
874 :
875 : /************************************************************************/
876 : /* SetColorTable() */
877 : /************************************************************************/
878 :
879 4 : CPLErr GDALPamRasterBand::SetColorTable( GDALColorTable *poTableIn )
880 :
881 : {
882 4 : PamInitialize();
883 :
884 4 : if( psPam )
885 : {
886 4 : if( psPam->poColorTable != NULL )
887 : {
888 0 : delete psPam->poColorTable;
889 0 : psPam->poColorTable = NULL;
890 : }
891 :
892 4 : if( poTableIn )
893 : {
894 4 : psPam->poColorTable = poTableIn->Clone();
895 4 : psPam->eColorInterp = GCI_PaletteIndex;
896 : }
897 :
898 4 : psPam->poParentDS->MarkPamDirty();
899 :
900 4 : return CE_None;
901 : }
902 : else
903 0 : return GDALRasterBand::SetColorTable( poTableIn );
904 :
905 : }
906 :
907 : /************************************************************************/
908 : /* SetColorInterpretation() */
909 : /************************************************************************/
910 :
911 512 : CPLErr GDALPamRasterBand::SetColorInterpretation( GDALColorInterp eInterpIn )
912 :
913 : {
914 512 : PamInitialize();
915 :
916 512 : if( psPam )
917 : {
918 509 : psPam->poParentDS->MarkPamDirty();
919 :
920 509 : psPam->eColorInterp = eInterpIn;
921 :
922 509 : return CE_None;
923 : }
924 : else
925 3 : return GDALRasterBand::SetColorInterpretation( eInterpIn );
926 : }
927 :
928 : /************************************************************************/
929 : /* GetColorInterpretation() */
930 : /************************************************************************/
931 :
932 157 : GDALColorInterp GDALPamRasterBand::GetColorInterpretation()
933 :
934 : {
935 157 : if( psPam )
936 135 : return psPam->eColorInterp;
937 : else
938 22 : return GDALRasterBand::GetColorInterpretation();
939 : }
940 :
941 : /************************************************************************/
942 : /* SetDescription() */
943 : /* */
944 : /* We let the GDALMajorObject hold the description, but we keep */
945 : /* track of whether it has been changed so we know to save it. */
946 : /************************************************************************/
947 :
948 371 : void GDALPamRasterBand::SetDescription( const char *pszDescription )
949 :
950 : {
951 371 : PamInitialize();
952 :
953 371 : if( psPam && strcmp(pszDescription,GetDescription()) != 0 )
954 342 : psPam->poParentDS->MarkPamDirty();
955 :
956 371 : GDALRasterBand::SetDescription( pszDescription );
957 371 : }
958 :
959 : /************************************************************************/
960 : /* PamParseHistogram() */
961 : /************************************************************************/
962 :
963 : int
964 1 : PamParseHistogram( CPLXMLNode *psHistItem,
965 : double *pdfMin, double *pdfMax,
966 : int *pnBuckets, int **ppanHistogram,
967 : int *pbIncludeOutOfRange, int *pbApproxOK )
968 :
969 : {
970 1 : if( psHistItem == NULL )
971 0 : return FALSE;
972 :
973 1 : *pdfMin = atof(CPLGetXMLValue( psHistItem, "HistMin", "0"));
974 1 : *pdfMax = atof(CPLGetXMLValue( psHistItem, "HistMax", "1"));
975 1 : *pnBuckets = atoi(CPLGetXMLValue( psHistItem, "BucketCount","2"));
976 1 : if (*pnBuckets <= 0)
977 0 : return FALSE;
978 :
979 1 : if( ppanHistogram == NULL )
980 0 : return TRUE;
981 :
982 : // Fetch the histogram and use it.
983 : int iBucket;
984 : const char *pszHistCounts = CPLGetXMLValue( psHistItem,
985 1 : "HistCounts", "" );
986 :
987 1 : *ppanHistogram = (int *) VSICalloc(sizeof(int),*pnBuckets);
988 1 : if (*ppanHistogram == NULL)
989 : {
990 : CPLError(CE_Failure, CPLE_OutOfMemory,
991 0 : "Cannot allocate memory for %d buckets", *pnBuckets);
992 0 : return FALSE;
993 : }
994 :
995 257 : for( iBucket = 0; iBucket < *pnBuckets; iBucket++ )
996 : {
997 256 : (*ppanHistogram)[iBucket] = atoi(pszHistCounts);
998 :
999 : // skip to next number.
1000 823 : while( *pszHistCounts != '\0' && *pszHistCounts != '|' )
1001 311 : pszHistCounts++;
1002 256 : if( *pszHistCounts == '|' )
1003 255 : pszHistCounts++;
1004 : }
1005 :
1006 1 : return TRUE;
1007 : }
1008 :
1009 : /************************************************************************/
1010 : /* PamFindMatchingHistogram() */
1011 : /************************************************************************/
1012 : CPLXMLNode *
1013 8 : PamFindMatchingHistogram( CPLXMLNode *psSavedHistograms,
1014 : double dfMin, double dfMax, int nBuckets,
1015 : int bIncludeOutOfRange, int bApproxOK )
1016 :
1017 : {
1018 8 : if( psSavedHistograms == NULL )
1019 6 : return NULL;
1020 :
1021 : CPLXMLNode *psXMLHist;
1022 4 : for( psXMLHist = psSavedHistograms->psChild;
1023 : psXMLHist != NULL; psXMLHist = psXMLHist->psNext )
1024 : {
1025 2 : if( psXMLHist->eType != CXT_Element
1026 : || !EQUAL(psXMLHist->pszValue,"HistItem") )
1027 0 : continue;
1028 :
1029 2 : double dfHistMin = atof(CPLGetXMLValue( psXMLHist, "HistMin", "0"));
1030 2 : double dfHistMax = atof(CPLGetXMLValue( psXMLHist, "HistMax", "0"));
1031 :
1032 2 : if( !(ARE_REAL_EQUAL(dfHistMin, dfMin))
1033 : || !(ARE_REAL_EQUAL(dfHistMax, dfMax))
1034 : || atoi(CPLGetXMLValue( psXMLHist,
1035 : "BucketCount","0")) != nBuckets
1036 : || !atoi(CPLGetXMLValue( psXMLHist,
1037 : "IncludeOutOfRange","0")) != !bIncludeOutOfRange
1038 : || (!bApproxOK && atoi(CPLGetXMLValue( psXMLHist,
1039 : "Approximate","0"))) )
1040 :
1041 2 : continue;
1042 :
1043 0 : return psXMLHist;
1044 : }
1045 :
1046 2 : return NULL;
1047 : }
1048 :
1049 : /************************************************************************/
1050 : /* PamHistogramToXMLTree() */
1051 : /************************************************************************/
1052 :
1053 : CPLXMLNode *
1054 8 : PamHistogramToXMLTree( double dfMin, double dfMax,
1055 : int nBuckets, int * panHistogram,
1056 : int bIncludeOutOfRange, int bApprox )
1057 :
1058 : {
1059 8 : char *pszHistCounts = (char *) CPLMalloc(12 * nBuckets + 10);
1060 : int iBucket, iHistOffset;
1061 : CPLXMLNode *psXMLHist;
1062 8 : CPLString oFmt;
1063 :
1064 8 : psXMLHist = CPLCreateXMLNode( NULL, CXT_Element, "HistItem" );
1065 :
1066 : CPLSetXMLValue( psXMLHist, "HistMin",
1067 8 : oFmt.Printf( "%.16g", dfMin ));
1068 : CPLSetXMLValue( psXMLHist, "HistMax",
1069 8 : oFmt.Printf( "%.16g", dfMax ));
1070 : CPLSetXMLValue( psXMLHist, "BucketCount",
1071 8 : oFmt.Printf( "%d", nBuckets ));
1072 : CPLSetXMLValue( psXMLHist, "IncludeOutOfRange",
1073 8 : oFmt.Printf( "%d", bIncludeOutOfRange ));
1074 : CPLSetXMLValue( psXMLHist, "Approximate",
1075 8 : oFmt.Printf( "%d", bApprox ));
1076 :
1077 8 : iHistOffset = 0;
1078 8 : pszHistCounts[0] = '\0';
1079 1310 : for( iBucket = 0; iBucket < nBuckets; iBucket++ )
1080 : {
1081 1302 : sprintf( pszHistCounts + iHistOffset, "%d", panHistogram[iBucket] );
1082 1302 : if( iBucket < nBuckets-1 )
1083 1294 : strcat( pszHistCounts + iHistOffset, "|" );
1084 1302 : iHistOffset += strlen(pszHistCounts+iHistOffset);
1085 : }
1086 :
1087 8 : CPLSetXMLValue( psXMLHist, "HistCounts", pszHistCounts );
1088 8 : CPLFree( pszHistCounts );
1089 :
1090 8 : return psXMLHist;
1091 : }
1092 :
1093 : /************************************************************************/
1094 : /* GetHistogram() */
1095 : /************************************************************************/
1096 :
1097 7 : CPLErr GDALPamRasterBand::GetHistogram( double dfMin, double dfMax,
1098 : int nBuckets, int * panHistogram,
1099 : int bIncludeOutOfRange, int bApproxOK,
1100 : GDALProgressFunc pfnProgress,
1101 : void *pProgressData )
1102 :
1103 : {
1104 7 : PamInitialize();
1105 :
1106 7 : if( psPam == NULL )
1107 : return GDALRasterBand::GetHistogram( dfMin, dfMax,
1108 : nBuckets, panHistogram,
1109 : bIncludeOutOfRange, bApproxOK,
1110 0 : pfnProgress, pProgressData );
1111 :
1112 : /* -------------------------------------------------------------------- */
1113 : /* Check if we have a matching histogram. */
1114 : /* -------------------------------------------------------------------- */
1115 : CPLXMLNode *psHistItem;
1116 :
1117 : psHistItem = PamFindMatchingHistogram( psPam->psSavedHistograms,
1118 : dfMin, dfMax, nBuckets,
1119 7 : bIncludeOutOfRange, bApproxOK );
1120 7 : if( psHistItem != NULL )
1121 : {
1122 0 : int *panTempHist = NULL;
1123 :
1124 0 : if( PamParseHistogram( psHistItem, &dfMin, &dfMax, &nBuckets,
1125 : &panTempHist,
1126 : &bIncludeOutOfRange, &bApproxOK ) )
1127 : {
1128 0 : memcpy( panHistogram, panTempHist, sizeof(int) * nBuckets );
1129 0 : CPLFree( panTempHist );
1130 0 : return CE_None;
1131 : }
1132 : }
1133 :
1134 : /* -------------------------------------------------------------------- */
1135 : /* We don't have an existing histogram matching the request, so */
1136 : /* generate one manually. */
1137 : /* -------------------------------------------------------------------- */
1138 : CPLErr eErr;
1139 :
1140 : eErr = GDALRasterBand::GetHistogram( dfMin, dfMax,
1141 : nBuckets, panHistogram,
1142 : bIncludeOutOfRange, bApproxOK,
1143 7 : pfnProgress, pProgressData );
1144 :
1145 : /* -------------------------------------------------------------------- */
1146 : /* Save an XML description of this histogram. */
1147 : /* -------------------------------------------------------------------- */
1148 7 : if( eErr == CE_None )
1149 : {
1150 : CPLXMLNode *psXMLHist;
1151 :
1152 : psXMLHist = PamHistogramToXMLTree( dfMin, dfMax, nBuckets,
1153 : panHistogram,
1154 7 : bIncludeOutOfRange, bApproxOK );
1155 7 : if( psXMLHist != NULL )
1156 : {
1157 7 : psPam->poParentDS->MarkPamDirty();
1158 :
1159 7 : if( psPam->psSavedHistograms == NULL )
1160 : psPam->psSavedHistograms = CPLCreateXMLNode( NULL, CXT_Element,
1161 5 : "Histograms" );
1162 :
1163 7 : CPLAddXMLChild( psPam->psSavedHistograms, psXMLHist );
1164 : }
1165 : }
1166 :
1167 7 : return eErr;
1168 : }
1169 :
1170 : /************************************************************************/
1171 : /* SetDefaultHistogram() */
1172 : /************************************************************************/
1173 :
1174 1 : CPLErr GDALPamRasterBand::SetDefaultHistogram( double dfMin, double dfMax,
1175 : int nBuckets, int *panHistogram)
1176 :
1177 : {
1178 : CPLXMLNode *psNode;
1179 :
1180 1 : PamInitialize();
1181 :
1182 1 : if( psPam == NULL )
1183 : return GDALRasterBand::SetDefaultHistogram( dfMin, dfMax,
1184 0 : nBuckets, panHistogram );
1185 :
1186 : /* -------------------------------------------------------------------- */
1187 : /* Do we have a matching histogram we should replace? */
1188 : /* -------------------------------------------------------------------- */
1189 : psNode = PamFindMatchingHistogram( psPam->psSavedHistograms,
1190 : dfMin, dfMax, nBuckets,
1191 1 : TRUE, TRUE );
1192 1 : if( psNode != NULL )
1193 : {
1194 : /* blow this one away */
1195 0 : CPLRemoveXMLChild( psPam->psSavedHistograms, psNode );
1196 0 : CPLDestroyXMLNode( psNode );
1197 : }
1198 :
1199 : /* -------------------------------------------------------------------- */
1200 : /* Translate into a histogram XML tree. */
1201 : /* -------------------------------------------------------------------- */
1202 : CPLXMLNode *psHistItem;
1203 :
1204 : psHistItem = PamHistogramToXMLTree( dfMin, dfMax, nBuckets,
1205 1 : panHistogram, TRUE, FALSE );
1206 :
1207 : /* -------------------------------------------------------------------- */
1208 : /* Insert our new default histogram at the front of the */
1209 : /* histogram list so that it will be the default histogram. */
1210 : /* -------------------------------------------------------------------- */
1211 1 : psPam->poParentDS->MarkPamDirty();
1212 :
1213 1 : if( psPam->psSavedHistograms == NULL )
1214 : psPam->psSavedHistograms = CPLCreateXMLNode( NULL, CXT_Element,
1215 1 : "Histograms" );
1216 :
1217 1 : psHistItem->psNext = psPam->psSavedHistograms->psChild;
1218 1 : psPam->psSavedHistograms->psChild = psHistItem;
1219 :
1220 1 : return CE_None;
1221 : }
1222 :
1223 : /************************************************************************/
1224 : /* GetDefaultHistogram() */
1225 : /************************************************************************/
1226 :
1227 : CPLErr
1228 7 : GDALPamRasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax,
1229 : int *pnBuckets, int **ppanHistogram,
1230 : int bForce,
1231 : GDALProgressFunc pfnProgress,
1232 : void *pProgressData )
1233 :
1234 : {
1235 7 : if( psPam && psPam->psSavedHistograms != NULL )
1236 : {
1237 : CPLXMLNode *psXMLHist;
1238 :
1239 2 : for( psXMLHist = psPam->psSavedHistograms->psChild;
1240 : psXMLHist != NULL; psXMLHist = psXMLHist->psNext )
1241 : {
1242 : int bApprox, bIncludeOutOfRange;
1243 :
1244 1 : if( psXMLHist->eType != CXT_Element
1245 : || !EQUAL(psXMLHist->pszValue,"HistItem") )
1246 0 : continue;
1247 :
1248 1 : if( PamParseHistogram( psXMLHist, pdfMin, pdfMax, pnBuckets,
1249 : ppanHistogram, &bIncludeOutOfRange,
1250 : &bApprox ) )
1251 1 : return CE_None;
1252 : else
1253 0 : return CE_Failure;
1254 : }
1255 : }
1256 :
1257 : return GDALRasterBand::GetDefaultHistogram( pdfMin, pdfMax, pnBuckets,
1258 : ppanHistogram, bForce,
1259 6 : pfnProgress, pProgressData );
1260 : }
1261 :
1262 : /************************************************************************/
1263 : /* GetDefaultRAT() */
1264 : /************************************************************************/
1265 :
1266 666 : const GDALRasterAttributeTable *GDALPamRasterBand::GetDefaultRAT()
1267 :
1268 : {
1269 666 : PamInitialize();
1270 :
1271 666 : if( psPam == NULL )
1272 69 : return GDALRasterBand::GetDefaultRAT();
1273 :
1274 597 : return psPam->poDefaultRAT;
1275 : }
1276 :
1277 : /************************************************************************/
1278 : /* SetDefaultRAT() */
1279 : /************************************************************************/
1280 :
1281 5 : CPLErr GDALPamRasterBand::SetDefaultRAT( const GDALRasterAttributeTable *poRAT)
1282 :
1283 : {
1284 5 : PamInitialize();
1285 :
1286 5 : if( psPam == NULL )
1287 0 : return GDALRasterBand::SetDefaultRAT( poRAT );
1288 :
1289 5 : psPam->poParentDS->MarkPamDirty();
1290 :
1291 5 : if( psPam->poDefaultRAT != NULL )
1292 : {
1293 0 : delete psPam->poDefaultRAT;
1294 0 : psPam->poDefaultRAT = NULL;
1295 : }
1296 :
1297 5 : if( poRAT == NULL )
1298 0 : psPam->poDefaultRAT = NULL;
1299 : else
1300 5 : psPam->poDefaultRAT = poRAT->Clone();
1301 :
1302 5 : return CE_None;
1303 : }
1304 :
|