LCOV - code coverage report
Current view: directory - gcore - gdaldefaultoverviews.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 369 322 87.3 %
Date: 2012-12-26 Functions: 18 16 88.9 %

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

Generated by: LCOV version 1.7