LCOV - code coverage report
Current view: directory - gcore - gdalpamrasterband.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 448 406 90.6 %
Date: 2011-12-18 Functions: 35 32 91.4 %

       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                 : 

Generated by: LCOV version 1.7