LCOV - code coverage report
Current view: directory - gcore - gdaldefaultoverviews.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 336 278 82.7 %
Date: 2010-01-09 Functions: 15 15 100.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: gdaldefaultoverviews.cpp 18333 2009-12-18 15:50:43Z warmerdam $
       3                 :  *
       4                 :  * Project:  GDAL Core
       5                 :  * Purpose:  Helper code to implement overview and mask support for many 
       6                 :  *           drivers with no inherent format support.
       7                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       8                 :  *
       9                 :  ******************************************************************************
      10                 :  * Copyright (c) 2000, 2007, Frank Warmerdam
      11                 :  *
      12                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      13                 :  * copy of this software and associated documentation files (the "Software"),
      14                 :  * to deal in the Software without restriction, including without limitation
      15                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      16                 :  * and/or sell copies of the Software, and to permit persons to whom the
      17                 :  * Software is furnished to do so, subject to the following conditions:
      18                 :  *
      19                 :  * The above copyright notice and this permission notice shall be included
      20                 :  * in all copies or substantial portions of the Software.
      21                 :  *
      22                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      23                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      24                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      25                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      26                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      27                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      28                 :  * DEALINGS IN THE SOFTWARE.
      29                 :  ****************************************************************************/
      30                 : 
      31                 : #include "gdal_priv.h"
      32                 : #include "cpl_string.h"
      33                 : 
      34                 : CPL_CVSID("$Id: gdaldefaultoverviews.cpp 18333 2009-12-18 15:50:43Z warmerdam $");
      35                 : 
      36                 : /************************************************************************/
      37                 : /*                        GDALDefaultOverviews()                        */
      38                 : /************************************************************************/
      39                 : 
      40           11859 : GDALDefaultOverviews::GDALDefaultOverviews()
      41                 : 
      42                 : {
      43           11859 :     poDS = NULL;
      44           11859 :     poODS = NULL;
      45           11859 :     bOvrIsAux = FALSE;
      46                 : 
      47           11859 :     bCheckedForMask = FALSE;
      48           11859 :     bCheckedForOverviews = FALSE;
      49                 : 
      50           11859 :     poMaskDS = NULL;
      51                 : 
      52           11859 :     bOwnMaskDS = FALSE;
      53           11859 :     poBaseDS = NULL;
      54                 : 
      55           11859 :     papszInitSiblingFiles = NULL;
      56           11859 :     pszInitName = NULL;
      57           11859 : }
      58                 : 
      59                 : /************************************************************************/
      60                 : /*                       ~GDALDefaultOverviews()                        */
      61                 : /************************************************************************/
      62                 : 
      63           11858 : GDALDefaultOverviews::~GDALDefaultOverviews()
      64                 : 
      65                 : {
      66           11858 :     CPLFree( pszInitName );
      67           11858 :     CSLDestroy( papszInitSiblingFiles );
      68                 : 
      69           11858 :     if( poODS != NULL )
      70                 :     {
      71              70 :         poODS->FlushCache();
      72              70 :         GDALClose( poODS );
      73              70 :         poODS = NULL;
      74                 :     }
      75                 : 
      76           11858 :     if( poMaskDS != NULL )
      77                 :     {
      78              10 :         if( bOwnMaskDS )
      79                 :         {
      80               7 :             poMaskDS->FlushCache();
      81               7 :             GDALClose( poMaskDS );
      82                 :         }
      83              10 :         poMaskDS = NULL;
      84                 :     }
      85           11858 : }
      86                 : 
      87                 : /************************************************************************/
      88                 : /*                           IsInitialized()                            */
      89                 : /*                                                                      */
      90                 : /*      Returns TRUE if we are initialized.                             */
      91                 : /************************************************************************/
      92                 : 
      93          302156 : int GDALDefaultOverviews::IsInitialized()
      94                 : 
      95                 : {
      96          302156 :     OverviewScan();
      97          302156 :     return poDS != NULL;
      98                 : }
      99                 : 
     100                 : /************************************************************************/
     101                 : /*                             Initialize()                             */
     102                 : /************************************************************************/
     103                 : 
     104            4544 : void GDALDefaultOverviews::Initialize( GDALDataset *poDSIn,
     105                 :                                        const char * pszBasename,
     106                 :                                        char **papszSiblingFiles,
     107                 :                                        int bNameIsOVR )
     108                 : 
     109                 : {
     110            4544 :     poDS = poDSIn;
     111                 :     
     112                 : /* -------------------------------------------------------------------- */
     113                 : /*      If we were already initialized, destroy the old overview        */
     114                 : /*      file handle.                                                    */
     115                 : /* -------------------------------------------------------------------- */
     116            4544 :     if( poODS != NULL )
     117                 :     {
     118               0 :         GDALClose( poODS );
     119               0 :         poODS = NULL;
     120                 : 
     121               0 :         CPLDebug( "GDAL", "GDALDefaultOverviews::Initialize() called twice - this is odd and perhaps dangerous!" );
     122                 :     }
     123                 : 
     124                 : /* -------------------------------------------------------------------- */
     125                 : /*      Store the initialization information for later use in           */
     126                 : /*      OverviewScan()                                                  */
     127                 : /* -------------------------------------------------------------------- */
     128            4544 :     bCheckedForOverviews = FALSE;
     129                 : 
     130            4544 :     CPLFree( pszInitName );
     131            4544 :     pszInitName = NULL;
     132            4544 :     if( pszBasename != NULL )
     133            4544 :         pszInitName = CPLStrdup(pszBasename);
     134            4544 :     bInitNameIsOVR = bNameIsOVR;
     135                 : 
     136            4544 :     CSLDestroy( papszInitSiblingFiles );
     137            4544 :     papszInitSiblingFiles = NULL;
     138            4544 :     if( papszSiblingFiles != NULL )
     139              45 :         papszInitSiblingFiles = CSLDuplicate(papszSiblingFiles);
     140            4544 : }
     141                 : 
     142                 : /************************************************************************/
     143                 : /*                            OverviewScan()                            */
     144                 : /*                                                                      */
     145                 : /*      This is called to scan for overview files when a first          */
     146                 : /*      request is made with regard to overviews.  It uses the          */
     147                 : /*      pszInitName, bInitNameIsOVR and papszInitSiblingFiles           */
     148                 : /*      information that was stored at Initialization() time.           */
     149                 : /************************************************************************/
     150                 : 
     151          302156 : void GDALDefaultOverviews::OverviewScan()
     152                 : 
     153                 : {
     154          302156 :     if( bCheckedForOverviews || poDS == NULL )
     155          300713 :         return;
     156                 : 
     157            1443 :     bCheckedForOverviews = true;
     158                 : 
     159            1443 :     CPLDebug( "GDAL", "GDALDefaultOverviews::OverviewScan()" );
     160                 : 
     161                 : /* -------------------------------------------------------------------- */
     162                 : /*      Open overview dataset if it exists.                             */
     163                 : /* -------------------------------------------------------------------- */
     164                 :     int bExists;
     165                 : 
     166            1443 :     if( pszInitName == NULL )
     167               0 :         pszInitName = CPLStrdup(poDS->GetDescription());
     168                 : 
     169            1443 :     if( !EQUAL(pszInitName,":::VIRTUAL:::") )
     170                 :     {
     171            1331 :         if( bInitNameIsOVR )
     172               0 :             osOvrFilename = pszInitName;
     173                 :         else
     174            1331 :             osOvrFilename.Printf( "%s.ovr", pszInitName );
     175                 : 
     176                 :         bExists = CPLCheckForFile( (char *) osOvrFilename.c_str(), 
     177            1331 :                                    papszInitSiblingFiles );
     178                 : 
     179                 : #if !defined(WIN32)
     180            1331 :         if( !bInitNameIsOVR && !bExists && !papszInitSiblingFiles )
     181                 :         {
     182            1285 :             osOvrFilename.Printf( "%s.OVR", pszInitName );
     183                 :             bExists = CPLCheckForFile( (char *) osOvrFilename.c_str(), 
     184            1285 :                                        papszInitSiblingFiles );
     185            1285 :             if( !bExists )
     186            1285 :                 osOvrFilename.Printf( "%s.ovr", pszInitName );
     187                 :         }
     188                 : #endif
     189                 : 
     190            1331 :         if( bExists )
     191                 :         {
     192              32 :             poODS = (GDALDataset*) GDALOpen( osOvrFilename, poDS->GetAccess() );
     193                 :         }
     194                 :     }
     195                 : 
     196                 : /* -------------------------------------------------------------------- */
     197                 : /*      We didn't find that, so try and find a corresponding aux        */
     198                 : /*      file.  Check that we are the dependent file of the aux          */
     199                 : /*      file.                                                           */
     200                 : /*                                                                      */
     201                 : /*      We only use the .aux file for overviews if they already have    */
     202                 : /*      overviews existing, or if USE_RRD is set true.                  */
     203                 : /* -------------------------------------------------------------------- */
     204            1443 :     if( !poODS && !EQUAL(pszInitName,":::VIRTUAL:::") )
     205                 :     {
     206                 :         poODS = GDALFindAssociatedAuxFile( pszInitName, poDS->GetAccess(),
     207            1299 :                                            poDS );
     208                 : 
     209            1299 :         if( poODS )
     210                 :         {
     211               2 :             int bUseRRD = CSLTestBoolean(CPLGetConfigOption("USE_RRD","NO"));
     212                 :             
     213               2 :             bOvrIsAux = TRUE;
     214               2 :             if( GetOverviewCount(1) == 0 && !bUseRRD )
     215                 :             {
     216               0 :                 bOvrIsAux = FALSE;
     217               0 :                 GDALClose( poODS );
     218               0 :                 poODS = NULL;
     219                 :             }
     220                 :             else
     221                 :             {
     222               2 :                 osOvrFilename = poODS->GetDescription();
     223                 :             }
     224                 :         }
     225                 :     }
     226                 : 
     227                 : /* -------------------------------------------------------------------- */
     228                 : /*      If we still don't have an overview, check to see if we have     */
     229                 : /*      overview metadata referencing a remote (ie. proxy) or local     */
     230                 : /*      subdataset overview dataset.                                    */
     231                 : /* -------------------------------------------------------------------- */
     232            1443 :     if( poODS == NULL )
     233                 :     {
     234                 :         const char *pszProxyOvrFilename = 
     235            1409 :             poDS->GetMetadataItem( "OVERVIEW_FILE", "OVERVIEWS" );
     236                 : 
     237            1409 :         if( pszProxyOvrFilename != NULL )
     238                 :         {
     239               5 :             if( EQUALN(pszProxyOvrFilename,":::BASE:::",10) )
     240                 :             {
     241               0 :                 CPLString osPath = CPLGetPath(poDS->GetDescription());
     242                 : 
     243                 :                 osOvrFilename =
     244               0 :                     CPLFormFilename( osPath, pszProxyOvrFilename+10, NULL );
     245                 :             }
     246                 :             else
     247               5 :                 osOvrFilename = pszProxyOvrFilename;
     248                 : 
     249               5 :             poODS = (GDALDataset *) GDALOpen(osOvrFilename,poDS->GetAccess());
     250                 :         }
     251                 :     }
     252                 : 
     253                 : /* -------------------------------------------------------------------- */
     254                 : /*      If we have an overview dataset, then mark all the overviews     */
     255                 : /*      with the base dataset  Used later for finding overviews         */
     256                 : /*      masks.  Uggg.                                                   */
     257                 : /* -------------------------------------------------------------------- */
     258            1443 :     if( poODS )
     259                 :     {
     260              39 :         int nOverviewCount = GetOverviewCount(1);
     261                 :         int iOver;
     262                 : 
     263              94 :         for( iOver = 0; iOver < nOverviewCount; iOver++ )
     264                 :         {
     265              55 :             GDALRasterBand *poBand = GetOverview( 1, iOver );
     266              55 :             GDALDataset    *poOverDS = NULL;
     267                 : 
     268              55 :             if( poBand != NULL )
     269              55 :                 poOverDS = poBand->GetDataset();
     270                 :             
     271              55 :             if( poOverDS != NULL )
     272                 :             {
     273              53 :                 poOverDS->oOvManager.poBaseDS = poDS;
     274              53 :                 poOverDS->oOvManager.poDS = poOverDS;
     275                 :             }
     276                 :         }
     277                 :     }
     278                 : }
     279                 : 
     280                 : /************************************************************************/
     281                 : /*                          GetOverviewCount()                          */
     282                 : /************************************************************************/
     283                 : 
     284             534 : int GDALDefaultOverviews::GetOverviewCount( int nBand )
     285                 : 
     286                 : {
     287                 :     GDALRasterBand * poBand;
     288                 : 
     289             534 :     if( poODS == NULL || nBand < 1 || nBand > poODS->GetRasterCount() )
     290             202 :         return 0;
     291                 : 
     292             332 :     poBand = poODS->GetRasterBand( nBand );
     293             332 :     if( poBand == NULL )
     294               0 :         return 0;
     295                 :     else
     296                 :     {
     297             332 :         if( bOvrIsAux )
     298               8 :             return poBand->GetOverviewCount();
     299                 :         else
     300             324 :             return poBand->GetOverviewCount() + 1;
     301                 :     }
     302                 : }
     303                 : 
     304                 : /************************************************************************/
     305                 : /*                            GetOverview()                             */
     306                 : /************************************************************************/
     307                 : 
     308                 : GDALRasterBand *
     309             306 : GDALDefaultOverviews::GetOverview( int nBand, int iOverview )
     310                 : 
     311                 : {
     312                 :     GDALRasterBand * poBand;
     313                 : 
     314             306 :     if( poODS == NULL || nBand < 1 || nBand > poODS->GetRasterCount() )
     315               0 :         return NULL;
     316                 : 
     317             306 :     poBand = poODS->GetRasterBand( nBand );
     318             306 :     if( poBand == NULL )
     319               0 :         return NULL;
     320                 : 
     321             306 :     if( bOvrIsAux )
     322               8 :         return poBand->GetOverview( iOverview );
     323                 : 
     324                 :     else // TIFF case, base is overview 0.
     325                 :     {
     326             298 :         if( iOverview == 0 )
     327             186 :             return poBand;
     328             112 :         else if( iOverview-1 >= poBand->GetOverviewCount() )
     329               0 :             return NULL;
     330                 :         else
     331             112 :             return poBand->GetOverview( iOverview-1 );
     332                 :     }
     333                 : }
     334                 : 
     335                 : /************************************************************************/
     336                 : /*                         GDALOvLevelAdjust()                          */
     337                 : /*                                                                      */
     338                 : /*      Some overview levels cannot be achieved closely enough to be    */
     339                 : /*      recognised as the desired overview level.  This function        */
     340                 : /*      will adjust an overview level to one that is achievable on      */
     341                 : /*      the given raster size.                                          */
     342                 : /*                                                                      */
     343                 : /*      For instance a 1200x1200 image on which a 256 level overview    */
     344                 : /*      is request will end up generating a 5x5 overview.  However,     */
     345                 : /*      this will appear to the system be a level 240 overview.         */
     346                 : /*      This function will adjust 256 to 240 based on knowledge of      */
     347                 : /*      the image size.                                                 */
     348                 : /************************************************************************/
     349                 : 
     350             157 : int GDALOvLevelAdjust( int nOvLevel, int nXSize )
     351                 : 
     352                 : {
     353             157 :     int nOXSize = (nXSize + nOvLevel - 1) / nOvLevel;
     354                 :     
     355             157 :     return (int) (0.5 + nXSize / (double) nOXSize);
     356                 : }
     357                 : 
     358                 : /************************************************************************/
     359                 : /*                           CleanOverviews()                           */
     360                 : /*                                                                      */
     361                 : /*      Remove all existing overviews.                                  */
     362                 : /************************************************************************/
     363                 : 
     364               4 : CPLErr GDALDefaultOverviews::CleanOverviews()
     365                 : 
     366                 : {
     367                 :     // Anything to do?
     368               4 :     if( poODS == NULL )
     369               1 :         return CE_None;
     370                 : 
     371                 :     // Delete the overview file(s). 
     372                 :     GDALDriver *poOvrDriver;
     373                 : 
     374               3 :     poOvrDriver = poODS->GetDriver();
     375               3 :     GDALClose( poODS );
     376               3 :     poODS = NULL;
     377                 : 
     378                 :     CPLErr eErr;
     379               3 :     if( poOvrDriver != NULL )
     380               3 :         eErr = poOvrDriver->Delete( osOvrFilename );
     381                 :     else
     382               0 :         eErr = CE_None;
     383                 : 
     384                 :     // Reset the saved overview filename. 
     385               3 :     if( !EQUAL(poDS->GetDescription(),":::VIRTUAL:::") )
     386                 :     {
     387               3 :         int bUseRRD = CSLTestBoolean(CPLGetConfigOption("USE_RRD","NO"));
     388                 : 
     389               3 :         if( bUseRRD )
     390               0 :             osOvrFilename = CPLResetExtension( poDS->GetDescription(), "aux" );
     391                 :         else
     392               3 :             osOvrFilename.Printf( "%s.ovr", poDS->GetDescription() );
     393                 :     }
     394                 :     else
     395               0 :         osOvrFilename = "";
     396                 : 
     397               3 :     return eErr;
     398                 : }
     399                 :     
     400                 : /************************************************************************/
     401                 : /*                      BuildOverviewsSubDataset()                      */
     402                 : /************************************************************************/
     403                 : 
     404                 : CPLErr
     405               4 : GDALDefaultOverviews::BuildOverviewsSubDataset( 
     406                 :     const char * pszPhysicalFile,
     407                 :     const char * pszResampling, 
     408                 :     int nOverviews, int * panOverviewList,
     409                 :     int nBands, int * panBandList,
     410                 :     GDALProgressFunc pfnProgress, void * pProgressData)
     411                 : 
     412                 : {
     413               4 :     if( osOvrFilename.length() == 0 )
     414                 :     {
     415               4 :         int iSequence = 0;
     416                 :         VSIStatBufL sStatBuf;
     417                 : 
     418               4 :         for( iSequence = 0; iSequence < 100; iSequence++ )
     419                 :         {
     420               4 :             osOvrFilename.Printf( "%s_%d.ovr", pszPhysicalFile, iSequence );
     421               4 :             if( VSIStatL( osOvrFilename, &sStatBuf ) != 0 )
     422                 :             {
     423               4 :                 CPLString osAdjustedOvrFilename;
     424                 : 
     425               4 :                 if( poDS->GetMOFlags() & GMO_PAM_CLASS )
     426                 :                 {
     427                 :                     osAdjustedOvrFilename.Printf( ":::BASE:::%s_%d.ovr",
     428                 :                                                   CPLGetFilename(pszPhysicalFile),
     429               4 :                                                   iSequence );
     430                 :                 }
     431                 :                 else
     432               0 :                     osAdjustedOvrFilename = osOvrFilename;
     433                 : 
     434                 :                 poDS->SetMetadataItem( "OVERVIEW_FILE", 
     435                 :                                        osAdjustedOvrFilename, 
     436               4 :                                        "OVERVIEWS" );
     437               4 :                 break;
     438                 :             }
     439                 :         }
     440                 : 
     441               4 :         if( iSequence == 100 )
     442               0 :             osOvrFilename = "";
     443                 :     }
     444                 : 
     445                 :     return BuildOverviews( NULL, pszResampling, nOverviews, panOverviewList,
     446               4 :                            nBands, panBandList, pfnProgress, pProgressData );
     447                 : }
     448                 : 
     449                 : /************************************************************************/
     450                 : /*                           BuildOverviews()                           */
     451                 : /************************************************************************/
     452                 : 
     453                 : CPLErr
     454              40 : GDALDefaultOverviews::BuildOverviews( 
     455                 :     const char * pszBasename,
     456                 :     const char * pszResampling, 
     457                 :     int nOverviews, int * panOverviewList,
     458                 :     int nBands, int * panBandList,
     459                 :     GDALProgressFunc pfnProgress, void * pProgressData)
     460                 : 
     461                 : {
     462                 :     GDALRasterBand **pahBands;
     463                 :     CPLErr       eErr;
     464                 :     int          i;
     465                 : 
     466              40 :     if( pfnProgress == NULL )
     467               0 :         pfnProgress = GDALDummyProgress;
     468                 : 
     469              40 :     if( nOverviews == 0 )
     470               4 :         return CleanOverviews();
     471                 : 
     472                 : /* -------------------------------------------------------------------- */
     473                 : /*      If we don't already have an overview file, we need to decide    */
     474                 : /*      what format to use.                                             */
     475                 : /* -------------------------------------------------------------------- */
     476              36 :     if( poODS == NULL )
     477                 :     {
     478              36 :         bOvrIsAux = CSLTestBoolean(CPLGetConfigOption( "USE_RRD", "NO" ));
     479              36 :         if( bOvrIsAux )
     480                 :         {
     481                 :             VSIStatBufL sStatBuf;
     482                 : 
     483               2 :             osOvrFilename = CPLResetExtension(poDS->GetDescription(),"aux");
     484                 : 
     485               2 :             if( VSIStatL( osOvrFilename, &sStatBuf ) == 0 )
     486               0 :                 osOvrFilename.Printf( "%s.aux", poDS->GetDescription() );
     487                 :         }
     488                 :     }
     489                 : /* -------------------------------------------------------------------- */
     490                 : /*      If we already have the overviews open, but they are             */
     491                 : /*      read-only, then try and reopen them read-write.                 */
     492                 : /* -------------------------------------------------------------------- */
     493               0 :     else if( poODS->GetAccess() == GA_ReadOnly )
     494                 :     {
     495               0 :         GDALClose( poODS );
     496               0 :         poODS = (GDALDataset *) GDALOpen( osOvrFilename, GA_Update );
     497               0 :         if( poODS == NULL )
     498               0 :             return CE_Failure;
     499                 :     }
     500                 : 
     501                 : /* -------------------------------------------------------------------- */
     502                 : /*      Our TIFF overview support currently only works safely if all    */
     503                 : /*      bands are handled at the same time.                             */
     504                 : /* -------------------------------------------------------------------- */
     505              36 :     if( !bOvrIsAux && nBands != poDS->GetRasterCount() )
     506                 :     {
     507                 :         CPLError( CE_Failure, CPLE_NotSupported,
     508                 :                   "Generation of overviews in external TIFF currently only"
     509                 :                   " supported when operating on all bands.\n" 
     510               0 :                   "Operation failed.\n" );
     511               0 :         return CE_Failure;
     512                 :     }
     513                 : 
     514                 : /* -------------------------------------------------------------------- */
     515                 : /*      If a basename is provided, use it to override the internal      */
     516                 : /*      overview filename.                                              */
     517                 : /* -------------------------------------------------------------------- */
     518              36 :     if( pszBasename == NULL && osOvrFilename.length() == 0  )
     519               0 :         pszBasename = poDS->GetDescription();
     520                 : 
     521              36 :     if( pszBasename != NULL )
     522                 :     {
     523               0 :         if( bOvrIsAux )
     524               0 :             osOvrFilename.Printf( "%s.aux", pszBasename );
     525                 :         else
     526               0 :             osOvrFilename.Printf( "%s.ovr", pszBasename );
     527                 :     }
     528                 : 
     529                 : /* -------------------------------------------------------------------- */
     530                 : /*      Establish which of the overview levels we already have, and     */
     531                 : /*      which are new.  We assume that band 1 of the file is            */
     532                 : /*      representative.                                                 */
     533                 : /* -------------------------------------------------------------------- */
     534              36 :     int   nNewOverviews, *panNewOverviewList = NULL;
     535              36 :     GDALRasterBand *poBand = poDS->GetRasterBand( 1 );
     536                 : 
     537              36 :     nNewOverviews = 0;
     538              36 :     panNewOverviewList = (int *) CPLCalloc(sizeof(int),nOverviews);
     539              87 :     for( i = 0; i < nOverviews && poBand != NULL; i++ )
     540                 :     {
     541                 :         int   j;
     542                 : 
     543              51 :         for( j = 0; j < poBand->GetOverviewCount(); j++ )
     544                 :         {
     545                 :             int    nOvFactor;
     546               0 :             GDALRasterBand * poOverview = poBand->GetOverview( j );
     547                 :  
     548                 :             nOvFactor = (int) 
     549               0 :                 (0.5 + poBand->GetXSize() / (double) poOverview->GetXSize());
     550                 : 
     551               0 :             if( nOvFactor == panOverviewList[i] 
     552                 :                 || nOvFactor == GDALOvLevelAdjust( panOverviewList[i], 
     553                 :                                                    poBand->GetXSize() ) )
     554               0 :                 panOverviewList[i] *= -1;
     555                 :         }
     556                 : 
     557              51 :         if( panOverviewList[i] > 0 )
     558              51 :             panNewOverviewList[nNewOverviews++] = panOverviewList[i];
     559                 :     }
     560                 : 
     561                 : /* -------------------------------------------------------------------- */
     562                 : /*      Build band list.                                                */
     563                 : /* -------------------------------------------------------------------- */
     564              36 :     pahBands = (GDALRasterBand **) CPLCalloc(sizeof(GDALRasterBand *),nBands);
     565              95 :     for( i = 0; i < nBands; i++ )
     566              59 :         pahBands[i] = poDS->GetRasterBand( panBandList[i] );
     567                 : 
     568                 : /* -------------------------------------------------------------------- */
     569                 : /*      Build new overviews - Imagine.  Keep existing file open if      */
     570                 : /*      we have it.  But mark all overviews as in need of               */
     571                 : /*      regeneration, since HFAAuxBuildOverviews() doesn't actually     */
     572                 : /*      produce the imagery.                                            */
     573                 : /* -------------------------------------------------------------------- */
     574                 : 
     575                 : #ifndef WIN32CE
     576                 : 
     577              36 :     if( bOvrIsAux )
     578                 :     {
     579                 :         eErr = HFAAuxBuildOverviews( osOvrFilename, poDS, &poODS,
     580                 :                                      nBands, panBandList,
     581                 :                                      nNewOverviews, panNewOverviewList, 
     582                 :                                      pszResampling, 
     583               2 :                                      pfnProgress, pProgressData );
     584                 : 
     585                 :         int j;
     586                 :         
     587               4 :         for( j = 0; j < nOverviews; j++ )
     588                 :         {
     589               2 :             if( panOverviewList[j] > 0 )
     590               2 :                 panOverviewList[j] *= -1;
     591                 :         }
     592                 :     }
     593                 : 
     594                 : /* -------------------------------------------------------------------- */
     595                 : /*      Build new overviews - TIFF.  Close TIFF files while we          */
     596                 : /*      operate on it.                                                  */
     597                 : /* -------------------------------------------------------------------- */
     598                 :     else
     599                 : #endif /* WIN32CE */
     600                 :     {
     601              34 :         if( poODS != NULL )
     602                 :         {
     603               0 :             delete poODS;
     604               0 :             poODS = NULL;
     605                 :         }
     606                 : 
     607                 :         eErr = GTIFFBuildOverviews( osOvrFilename, nBands, pahBands, 
     608                 :                                     nNewOverviews, panNewOverviewList, 
     609              34 :                                     pszResampling, pfnProgress, pProgressData );
     610                 :         
     611                 :         // Probe for proxy overview filename. 
     612              34 :         if( eErr == CE_Failure )
     613                 :         {
     614                 :             const char *pszProxyOvrFilename = 
     615               2 :                 poDS->GetMetadataItem("FILENAME","ProxyOverviewRequest");
     616                 : 
     617               2 :             if( pszProxyOvrFilename != NULL )
     618                 :             {
     619               0 :                 osOvrFilename = pszProxyOvrFilename;
     620                 :                 eErr = GTIFFBuildOverviews( osOvrFilename, nBands, pahBands, 
     621                 :                                             nNewOverviews, panNewOverviewList, 
     622                 :                                             pszResampling, 
     623               0 :                                             pfnProgress, pProgressData );
     624                 :             }
     625                 :         }
     626                 : 
     627              34 :         if( eErr == CE_None )
     628                 :         {
     629              32 :             poODS = (GDALDataset *) GDALOpen( osOvrFilename, GA_Update );
     630              32 :             if( poODS == NULL )
     631               0 :                 eErr = CE_Failure;
     632                 :         }
     633                 :     }
     634                 : 
     635                 : /* -------------------------------------------------------------------- */
     636                 : /*      Refresh old overviews that were listed.                         */
     637                 : /* -------------------------------------------------------------------- */
     638                 :     GDALRasterBand **papoOverviewBands;
     639                 : 
     640                 :     papoOverviewBands = (GDALRasterBand **) 
     641              36 :         CPLCalloc(sizeof(void*),nOverviews);
     642                 : 
     643              93 :     for( int iBand = 0; iBand < nBands && eErr == CE_None; iBand++ )
     644                 :     {
     645              57 :         poBand = poDS->GetRasterBand( panBandList[iBand] );
     646                 : 
     647              57 :         nNewOverviews = 0;
     648             148 :         for( i = 0; i < nOverviews && poBand != NULL; i++ )
     649                 :         {
     650                 :             int   j;
     651                 :             
     652             238 :             for( j = 0; j < poBand->GetOverviewCount(); j++ )
     653                 :             {
     654                 :                 int    nOvFactor;
     655             153 :                 GDALRasterBand * poOverview = poBand->GetOverview( j );
     656                 : 
     657                 :                 int bHasNoData;
     658             153 :                 double noDataValue = poBand->GetNoDataValue(&bHasNoData);
     659                 : 
     660             153 :                 if (bHasNoData)
     661               5 :                   poOverview->SetNoDataValue(noDataValue);
     662                 : 
     663                 :                 nOvFactor = (int) 
     664             153 :                     (0.5 + poBand->GetXSize() / (double) poOverview->GetXSize());
     665                 : 
     666             304 :                 if( nOvFactor == - panOverviewList[i] 
     667             151 :                     || nOvFactor == GDALOvLevelAdjust( -panOverviewList[i], 
     668                 :                                                        poBand->GetXSize() ) )
     669                 :                 {
     670               6 :                     papoOverviewBands[nNewOverviews++] = poOverview;
     671               6 :                     break;
     672                 :                 }
     673                 :             }
     674                 :         }
     675                 : 
     676              57 :         if( nNewOverviews > 0 )
     677                 :         {
     678                 :             eErr = GDALRegenerateOverviews( (GDALRasterBandH) poBand, 
     679                 :                                             nNewOverviews, 
     680                 :                                             (GDALRasterBandH*)papoOverviewBands,
     681                 :                                             pszResampling, 
     682               4 :                                             pfnProgress, pProgressData );
     683                 :         }
     684                 :     }
     685                 : 
     686                 : /* -------------------------------------------------------------------- */
     687                 : /*      Cleanup                                                         */
     688                 : /* -------------------------------------------------------------------- */
     689              36 :     CPLFree( papoOverviewBands );
     690              36 :     CPLFree( panNewOverviewList );
     691              36 :     CPLFree( pahBands );
     692                 : 
     693                 : /* -------------------------------------------------------------------- */
     694                 : /*      If we have a mask file, we need to build it's overviews         */
     695                 : /*      too.                                                            */
     696                 : /* -------------------------------------------------------------------- */
     697              36 :     if( HaveMaskFile() && poMaskDS )
     698                 :     {
     699                 :         poMaskDS->BuildOverviews( pszResampling, nOverviews, panOverviewList,
     700               1 :                                   0, NULL, pfnProgress, pProgressData );
     701               1 :         if( bOwnMaskDS )
     702               1 :             GDALClose( poMaskDS );
     703                 : 
     704                 :         // force next request to reread mask file.
     705               1 :         poMaskDS = NULL;
     706               1 :         bOwnMaskDS = FALSE;
     707               1 :         bCheckedForMask = FALSE;
     708                 :     }
     709                 : 
     710                 : /* -------------------------------------------------------------------- */
     711                 : /*      If we have an overview dataset, then mark all the overviews     */
     712                 : /*      with the base dataset  Used later for finding overviews         */
     713                 : /*      masks.  Uggg.                                                   */
     714                 : /* -------------------------------------------------------------------- */
     715              36 :     if( poODS )
     716                 :     {
     717              34 :         int nOverviewCount = GetOverviewCount(1);
     718                 :         int iOver;
     719                 : 
     720              83 :         for( iOver = 0; iOver < nOverviewCount; iOver++ )
     721                 :         {
     722              49 :             GDALRasterBand *poBand = GetOverview( 1, iOver );
     723              49 :             GDALDataset    *poOverDS = NULL;
     724                 : 
     725              49 :             if( poBand != NULL )
     726              49 :                 poOverDS = poBand->GetDataset();
     727                 : 
     728              49 :             if (poOverDS != NULL)
     729                 :             {
     730              47 :                 poOverDS->oOvManager.poBaseDS = poDS;
     731              47 :                 poOverDS->oOvManager.poDS = poOverDS;
     732                 :             }
     733                 :         }
     734                 :     }
     735                 : 
     736              36 :     return eErr;
     737                 : }
     738                 : 
     739                 : /************************************************************************/
     740                 : /*                           CreateMaskBand()                           */
     741                 : /************************************************************************/
     742                 : 
     743               2 : CPLErr GDALDefaultOverviews::CreateMaskBand( int nFlags, int nBand )
     744                 : 
     745                 : {
     746               2 :     if( nBand < 1 )
     747               2 :         nFlags |= GMF_PER_DATASET;
     748                 : 
     749                 : /* -------------------------------------------------------------------- */
     750                 : /*      ensure existing file gets opened if there is one.               */
     751                 : /* -------------------------------------------------------------------- */
     752               2 :     HaveMaskFile();
     753                 : 
     754                 : /* -------------------------------------------------------------------- */
     755                 : /*      Try creating the mask file.                                     */
     756                 : /* -------------------------------------------------------------------- */
     757               2 :     if( poMaskDS == NULL )
     758                 :     {
     759               2 :         CPLString osMskFilename;
     760               2 :         GDALDriver *poDr = (GDALDriver *) GDALGetDriverByName( "GTiff" );
     761               2 :         char **papszOpt = NULL;
     762                 :         int  nBX, nBY;
     763                 :         int  nBands;
     764                 :         
     765               2 :         if( poDr == NULL )
     766               0 :             return CE_Failure;
     767                 : 
     768               2 :         GDALRasterBand *poTBand = poDS->GetRasterBand(1);
     769               2 :         if( poTBand == NULL )
     770               0 :             return CE_Failure;
     771                 : 
     772               2 :         if( nFlags & GMF_PER_DATASET )
     773               2 :             nBands = 1;
     774                 :         else
     775               0 :             nBands = poDS->GetRasterCount();
     776                 : 
     777                 : 
     778               2 :         papszOpt = CSLSetNameValue( papszOpt, "COMPRESS", "DEFLATE" );
     779               2 :         papszOpt = CSLSetNameValue( papszOpt, "INTERLEAVE", "BAND" );
     780                 : 
     781               2 :         poTBand->GetBlockSize( &nBX, &nBY );
     782                 : 
     783                 :         // try to create matching tile size if legal in TIFF.
     784               2 :         if( (nBX % 16) == 0 && (nBY % 16) == 0 )
     785                 :         {
     786               0 :             papszOpt = CSLSetNameValue( papszOpt, "TILED", "YES" );
     787                 :             papszOpt = CSLSetNameValue( papszOpt, "BLOCKXSIZE",
     788               0 :                                         CPLString().Printf("%d",nBX) );
     789                 :             papszOpt = CSLSetNameValue( papszOpt, "BLOCKYSIZE",
     790               0 :                                         CPLString().Printf("%d",nBY) );
     791                 :         }
     792                 : 
     793               2 :         osMskFilename.Printf( "%s.msk", poDS->GetDescription() );
     794                 :         poMaskDS = poDr->Create( osMskFilename, 
     795                 :                                  poDS->GetRasterXSize(),
     796                 :                                  poDS->GetRasterYSize(),
     797               2 :                                  nBands, GDT_Byte, papszOpt );
     798               2 :         CSLDestroy( papszOpt );
     799                 : 
     800               2 :         if( poMaskDS == NULL ) // presumably error already issued.
     801               0 :             return CE_Failure;
     802                 : 
     803               2 :         bOwnMaskDS = TRUE;
     804                 :     }
     805                 :         
     806                 : /* -------------------------------------------------------------------- */
     807                 : /*      Save the mask flags for this band.                              */
     808                 : /* -------------------------------------------------------------------- */
     809               2 :     if( nBand > poMaskDS->GetRasterCount() )
     810                 :     {
     811                 :         CPLError( CE_Failure, CPLE_AppDefined,
     812                 :                   "Attempt to create a mask band for band %d of %s,\n"
     813                 :                   "but the .msk file has a PER_DATASET mask.", 
     814               0 :                   nBand, poDS->GetDescription() );
     815               0 :         return CE_Failure;
     816                 :     }
     817                 :     
     818                 :     int iBand; 
     819                 : 
     820              12 :     for( iBand = 0; iBand < poDS->GetRasterCount(); iBand++ )
     821                 :     {
     822                 :         // we write only the info for this band, unless we are
     823                 :         // using PER_DATASET in which case we write for all.
     824                 :         if( nBand != iBand + 1 && !(nFlags | GMF_PER_DATASET) )
     825                 :             continue;
     826                 : 
     827                 :         poMaskDS->SetMetadataItem( 
     828                 :             CPLString().Printf("INTERNAL_MASK_FLAGS_%d", iBand+1 ),
     829               4 :             CPLString().Printf("%d", nFlags ) );
     830                 :     }
     831                 : 
     832               2 :     return CE_None;
     833                 : }
     834                 : 
     835                 : /************************************************************************/
     836                 : /*                            GetMaskBand()                             */
     837                 : /************************************************************************/
     838                 : 
     839               8 : GDALRasterBand *GDALDefaultOverviews::GetMaskBand( int nBand )
     840                 : 
     841                 : {
     842               8 :     int nFlags = GetMaskFlags( nBand );
     843                 : 
     844               8 :     if( nFlags == 0x8000 ) // secret code meaning we don't handle this band.
     845               0 :         return NULL;
     846                 :         
     847               8 :     if( nFlags & GMF_PER_DATASET )
     848               8 :         return poMaskDS->GetRasterBand(1);
     849                 : 
     850               0 :     if( nBand > 0 )
     851               0 :         return poMaskDS->GetRasterBand( nBand );
     852                 :     else 
     853               0 :         return NULL;
     854                 : }
     855                 : 
     856                 : /************************************************************************/
     857                 : /*                            GetMaskFlags()                            */
     858                 : /************************************************************************/
     859                 : 
     860              16 : int GDALDefaultOverviews::GetMaskFlags( int nBand )
     861                 : 
     862                 : {
     863                 : /* -------------------------------------------------------------------- */
     864                 : /*      Fetch this band's metadata entry.  They are of the form:        */
     865                 : /*        INTERNAL_MASK_FLAGS_n: flags                                  */
     866                 : /* -------------------------------------------------------------------- */
     867              16 :     if( !HaveMaskFile() )
     868               0 :         return 0;
     869                 :     
     870                 :     const char *pszValue = 
     871                 :         poMaskDS->GetMetadataItem( 
     872              16 :             CPLString().Printf( "INTERNAL_MASK_FLAGS_%d", MAX(nBand,1)) );
     873                 : 
     874              16 :     if( pszValue == NULL )
     875               0 :         return 0x8000;
     876                 :     else
     877              16 :         return atoi(pszValue);
     878                 : }
     879                 : 
     880                 : /************************************************************************/
     881                 : /*                            HaveMaskFile()                            */
     882                 : /*                                                                      */
     883                 : /*      Check for a mask file if we haven't already done so.            */
     884                 : /*      Returns TRUE if we have one, otherwise FALSE.                   */
     885                 : /************************************************************************/
     886                 : 
     887            1703 : int GDALDefaultOverviews::HaveMaskFile( char ** papszSiblingFiles,
     888                 :                                         const char *pszBasename )
     889                 : 
     890                 : {
     891                 : /* -------------------------------------------------------------------- */
     892                 : /*      Have we already checked for masks?                              */
     893                 : /* -------------------------------------------------------------------- */
     894            1703 :     if( bCheckedForMask )
     895             199 :         return poMaskDS != NULL;
     896                 : 
     897            1504 :     if( papszSiblingFiles == NULL )
     898            1504 :         papszSiblingFiles = papszInitSiblingFiles;
     899                 : 
     900                 : /* -------------------------------------------------------------------- */
     901                 : /*      Are we an overview?  If so we need to find the corresponding    */
     902                 : /*      overview in the base files mask file (if there is one).         */
     903                 : /* -------------------------------------------------------------------- */
     904            1504 :     if( poBaseDS != NULL && poBaseDS->oOvManager.HaveMaskFile() )
     905                 :     {
     906               3 :         int iOver, nOverviewCount = 0;
     907               3 :         GDALRasterBand *poBaseBand = poBaseDS->GetRasterBand(1);
     908               3 :         GDALRasterBand *poBaseMask = NULL;
     909                 : 
     910               3 :         if( poBaseBand != NULL )
     911               3 :             poBaseMask = poBaseBand->GetMaskBand();
     912               3 :         if( poBaseMask )
     913               3 :             nOverviewCount = poBaseMask->GetOverviewCount();
     914                 : 
     915               5 :         for( iOver = 0; iOver < nOverviewCount; iOver++ )
     916                 :         {
     917               5 :             GDALRasterBand *poOverBand = poBaseMask->GetOverview( iOver );
     918                 :             
     919               5 :             if( poOverBand->GetXSize() == poDS->GetRasterXSize() 
     920                 :                 && poOverBand->GetYSize() == poDS->GetRasterYSize() )
     921                 :             {
     922               3 :                 poMaskDS = poOverBand->GetDataset();
     923               3 :                 break;
     924                 :             }
     925                 :         }
     926                 : 
     927               3 :         bCheckedForMask = TRUE;
     928               3 :         bOwnMaskDS = FALSE;
     929                 :         
     930                 :         CPLAssert( poMaskDS != poDS );
     931                 : 
     932               3 :         return poMaskDS != NULL;
     933                 :     }
     934                 : 
     935                 : /* -------------------------------------------------------------------- */
     936                 : /*      Are we even initialized?  If not, we apparently don't want      */
     937                 : /*      to support overviews and masks.                                 */
     938                 : /* -------------------------------------------------------------------- */
     939            1501 :     if( !IsInitialized() )
     940             133 :         return FALSE;
     941                 : 
     942                 : /* -------------------------------------------------------------------- */
     943                 : /*      Check for .msk file.                                            */
     944                 : /* -------------------------------------------------------------------- */
     945            1368 :     CPLString osMskFilename;
     946            1368 :     bCheckedForMask = TRUE;
     947                 : 
     948            1368 :     if( pszBasename == NULL )
     949            1368 :         pszBasename = poDS->GetDescription();
     950                 : 
     951                 :     // Don't bother checking for masks of masks. 
     952            1368 :     if( EQUAL(CPLGetExtension(pszBasename),".msk") )
     953               0 :         return FALSE;
     954                 : 
     955            1368 :     osMskFilename.Printf( "%s.msk", pszBasename );
     956                 : 
     957                 :     int bExists = CPLCheckForFile( (char *) osMskFilename.c_str(), 
     958            1368 :                                    papszSiblingFiles );
     959                 : 
     960                 : #if !defined(WIN32)
     961            1368 :     if( !bExists && !papszSiblingFiles )
     962                 :     {
     963            1350 :         osMskFilename.Printf( "%s.MSK", pszBasename );
     964                 :         bExists = CPLCheckForFile( (char *) osMskFilename.c_str(), 
     965            1350 :                                    papszSiblingFiles );
     966                 :     }
     967                 : #endif
     968                 : 
     969            1368 :     if( !bExists )
     970            1362 :         return FALSE;
     971                 : 
     972                 : /* -------------------------------------------------------------------- */
     973                 : /*      Open the file.                                                  */
     974                 : /* -------------------------------------------------------------------- */
     975               6 :     poMaskDS = (GDALDataset *) GDALOpen( osMskFilename, poDS->GetAccess() );
     976                 :     CPLAssert( poMaskDS != poDS );
     977                 : 
     978               6 :     if( poMaskDS == NULL )
     979               0 :         return FALSE;
     980                 : 
     981               6 :     bOwnMaskDS = TRUE;
     982                 :     
     983               6 :     return TRUE;
     984                 : }

Generated by: LCOV version 1.7