LCOV - code coverage report
Current view: directory - gcore - gdalpamrasterband.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 415 330 79.5 %
Date: 2010-01-09 Functions: 32 30 93.8 %

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

Generated by: LCOV version 1.7