LTP GCOV extension - code coverage report
Current view: directory - gcore - gdalpamrasterband.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 416
Code covered: 80.5 % Executed lines: 335

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

Generated by: LTP GCOV extension version 1.5