LCOV - code coverage report
Current view: directory - gcore - gdalpamrasterband.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 454 414 91.2 %
Date: 2012-12-26 Functions: 35 32 91.4 %

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

Generated by: LCOV version 1.7