LCOV - code coverage report
Current view: directory - gcore - gdaldefaultoverviews.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 365 308 84.4 %
Date: 2011-12-18 Functions: 18 16 88.9 %

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

Generated by: LCOV version 1.7