Main Page Class Hierarchy Compound List File List Compound Members File Members Related Pages

# gdaldefaultoverviews.cpp

    00001 /******************************************************************************
    00002  * $Id: gdaldefaultoverviews_cpp-source.html,v 1.8 2001/07/05 13:24:08 warmerda Exp $
    00003  *
    00004  * Project:  GDAL Core
    00005  * Purpose:  Helper code to implement overview support in different drivers.
    00006  * Author:   Frank Warmerdam, warmerda@home.com
    00007  *
    00008  ******************************************************************************
    00009  * Copyright (c) 2000, Frank Warmerdam
    00010  *
    00011  * Permission is hereby granted, free of charge, to any person obtaining a
    00012  * copy of this software and associated documentation files (the "Software"),
    00013  * to deal in the Software without restriction, including without limitation
    00014  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
    00015  * and/or sell copies of the Software, and to permit persons to whom the
    00016  * Software is furnished to do so, subject to the following conditions:
    00017  *
    00018  * The above copyright notice and this permission notice shall be included
    00019  * in all copies or substantial portions of the Software.
    00020  *
    00021  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
    00022  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    00023  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
    00024  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    00025  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    00026  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    00027  * DEALINGS IN THE SOFTWARE.
    00028  ******************************************************************************
    00029  *
    00030  * $Log: gdaldefaultoverviews_cpp-source.html,v $
    00030  * Revision 1.8  2001/07/05 13:24:08  warmerda
    00030  * *** empty log message ***
    00030  *
    00031  * Revision 1.6  2001/06/22 21:00:38  warmerda
    00032  * fixed several problems with regenerating existing overviews
    00033  *
    00034  * Revision 1.5  2001/06/22 13:52:03  warmerda
    00035  * fixed bug when refreshing overviews during build
    00036  *
    00037  * Revision 1.4  2001/06/20 16:08:54  warmerda
    00038  * GDALDefaultOverviews now remembers ovr filename, and allows explicit setting
    00039  *
    00040  * Revision 1.3  2000/06/19 18:48:49  warmerda
    00041  * fixed message
    00042  *
    00043  * Revision 1.2  2000/06/19 14:42:27  warmerda
    00044  * Don't close old overviews till after we have identified which already
    00045  * exist, otherwise multiple copies of overviews may be created.
    00046  *
    00047  * Revision 1.1  2000/04/21 21:54:05  warmerda
    00048  * New
    00049  *
    00050  */
    00051
    00052 #include "gdal_priv.h"
    00053
    00054 /************************************************************************/
    00055 /*                        GDALDefaultOverviews()                        */
    00056 /************************************************************************/
    00057
    00058 GDALDefaultOverviews::GDALDefaultOverviews()
    00059
    00060 {
    00061     poDS = NULL;
    00062     poODS = NULL;
    00063     pszOvrFilename = NULL;
    00064 }
    00065
    00066 /************************************************************************/
    00067 /*                       ~GDALDefaultOverviews()                        */
    00068 /************************************************************************/
    00069
    00070 GDALDefaultOverviews::~GDALDefaultOverviews()
    00071
    00072 {
    00073     if( poODS != NULL )
    00074     {
    00075         poODS->FlushCache();
    00076         delete poODS;
    00077     }
    00078     CPLFree( pszOvrFilename );
    00079 }
    00080
    00081 /************************************************************************/
    00082 /*                             Initialize()                             */
    00083 /************************************************************************/
    00084
    00085 void GDALDefaultOverviews::Initialize( GDALDataset *poDS,
    00086                                        const char * pszBasename,
    00087                                        int bNameIsOVR )
    00088
    00089 {
    00090     VSIStatBuf sStatBuf;
    00091
    00092 /* -------------------------------------------------------------------- */
    00093 /*      If we were already initialized, destroy the old overview        */
    00094 /*      file handle.                                                    */
    00095 /* -------------------------------------------------------------------- */
    00096     if( this->poODS != NULL )
    00097     {
    00098         delete poODS;
    00099     }
    00100
    00101 /* -------------------------------------------------------------------- */
    00102 /*      Open overview dataset if it exists.                             */
    00103 /* -------------------------------------------------------------------- */
    00104     this->poDS = poDS;
    00105
    00106     if( pszBasename == NULL )
    00107         pszBasename = poDS->GetDescription();
    00108
    00109     CPLFree( pszOvrFilename );
    00110     pszOvrFilename = (char *) CPLMalloc(strlen(pszBasename)+5);
    00111     if( bNameIsOVR )
    00112         strcpy( pszOvrFilename, pszBasename );
    00113     else
    00114         sprintf( pszOvrFilename, "%s.ovr", pszBasename );
    00115
    00116     if( VSIStat( pszOvrFilename, &sStatBuf ) == 0 )
    00117         poODS = (GDALDataset *) GDALOpen( pszOvrFilename, poDS->GetAccess() );
    00118 }
    00119
    00120 /************************************************************************/
    00121 /*                          GetOverviewCount()                          */
    00122 /************************************************************************/
    00123
    00124 int GDALDefaultOverviews::GetOverviewCount( int nBand )
    00125
    00126 {
    00127     GDALRasterBand * poBand;
    00128
    00129     if( poODS == NULL || nBand < 1 || nBand > poODS->GetRasterCount() )
    00130         return 0;
    00131
    00132     poBand = poODS->GetRasterBand( nBand );
    00133     if( poBand == NULL )
    00134         return 0;
    00135     else
    00136         return poBand->GetOverviewCount() + 1;
    00137 }
    00138
    00139 /************************************************************************/
    00140 /*                            GetOverview()                             */
    00141 /************************************************************************/
    00142
    00143 GDALRasterBand *
    00144 GDALDefaultOverviews::GetOverview( int nBand, int iOverview )
    00145
    00146 {
    00147     GDALRasterBand * poBand;
    00148
    00149     if( poODS == NULL || nBand < 1 || nBand > poODS->GetRasterCount() )
    00150         return NULL;
    00151
    00152     poBand = poODS->GetRasterBand( nBand );
    00153     if( poBand == NULL )
    00154         return NULL;
    00155
    00156     if( iOverview == 0 )
    00157         return poBand;
    00158     else if( iOverview-1 >= poBand->GetOverviewCount() )
    00159         return NULL;
    00160     else
    00161         return poBand->GetOverview( iOverview-1 );
    00162 }
    00163
    00164 /************************************************************************/
    00165 /*                         GDALOvLevelAdjust()                          */
    00166 /*                                                                      */
    00167 /*      Some overview levels cannot be achieved closely enough to be    */
    00168 /*      recognised as the desired overview level.  This function        */
    00169 /*      will adjust an overview level to one that is achievable on      */
    00170 /*      the given raster size.                                          */
    00171 /*                                                                      */
    00172 /*      For instance a 1200x1200 image on which a 256 level overview    */
    00173 /*      is request will end up generating a 5x5 overview.  However,     */
    00174 /*      this will appear to the system be a level 240 overview.         */
    00175 /*      This function will adjust 256 to 240 based on knowledge of      */
    00176 /*      the image size.                                                 */
    00177 /************************************************************************/
    00178
    00179 static int GDALOvLevelAdjust( int nOvLevel, int nXSize )
    00180
    00181 {
    00182     int nOXSize = (nXSize + nOvLevel - 1) / nOvLevel;
    00183
    00184     return (int) (0.5 + nXSize / (double) nOXSize);
    00185 }
    00186
    00187 /************************************************************************/
    00188 /*                     GDALDefaultBuildOverviews()                      */
    00189 /************************************************************************/
    00190
    00191 CPLErr
    00192 GDALDefaultOverviews::BuildOverviews(
    00193     const char * pszBasename,
    00194     const char * pszResampling,
    00195     int nOverviews, int * panOverviewList,
    00196     int nBands, int * panBandList,
    00197     GDALProgressFunc pfnProgress, void * pProgressData)
    00198
    00199 {
    00200     GDALRasterBand **pahBands;
    00201     CPLErr       eErr;
    00202     int          i;
    00203
    00204 /* -------------------------------------------------------------------- */
    00205 /*      Our TIFF overview support currently only works safely if all    */
    00206 /*      bands are handled at the same time.                             */
    00207 /* -------------------------------------------------------------------- */
    00208     if( nBands != poDS->GetRasterCount() )
    00209     {
    00210         CPLError( CE_Failure, CPLE_NotSupported,
    00211                   "Generation of overviews in external TIFF currently only"
    00212                   " supported when operating on all bands.\n"
    00213                   "Operation failed.\n" );
    00214         return CE_Failure;
    00215     }
    00216
    00217 /* -------------------------------------------------------------------- */
    00218 /*      If a basename is provided, use it to override the internal      */
    00219 /*      overview filename.                                              */
    00220 /* -------------------------------------------------------------------- */
    00221     if( pszBasename == NULL && pszOvrFilename == NULL )
    00222         pszBasename = poDS->GetDescription();
    00223
    00224     if( pszBasename != NULL )
    00225     {
    00226         CPLFree( pszOvrFilename );
    00227         pszOvrFilename = (char *) CPLMalloc(strlen(pszBasename)+5);
    00228         sprintf( pszOvrFilename, "%s.ovr", pszBasename );
    00229     }
    00230
    00231 /* -------------------------------------------------------------------- */
    00232 /*      Establish which of the overview levels we already have, and     */
    00233 /*      which are new.  We assume that band 1 of the file is            */
    00234 /*      representative.                                                 */
    00235 /* -------------------------------------------------------------------- */
    00236     int   nNewOverviews, *panNewOverviewList = NULL;
    00237     GDALRasterBand *poBand = poDS->GetRasterBand( 1 );
    00238
    00239     nNewOverviews = 0;
    00240     panNewOverviewList = (int *) CPLCalloc(sizeof(int),nOverviews);
    00241     for( i = 0; i < nOverviews && poBand != NULL; i++ )
    00242     {
    00243         int   j;
    00244
    00245         for( j = 0; j < poBand->GetOverviewCount(); j++ )
    00246         {
    00247             int    nOvFactor;
    00248             GDALRasterBand * poOverview = poBand->GetOverview( j );
    00249
    00250             nOvFactor = (int)
    00251                 (0.5 + poBand->GetXSize() / (double) poOverview->GetXSize());
    00252
    00253             if( nOvFactor == panOverviewList[i]
    00254                 || nOvFactor == GDALOvLevelAdjust( panOverviewList[i],
    00255                                                    poBand->GetXSize() ) )
    00256                 panOverviewList[i] *= -1;
    00257         }
    00258
    00259         if( panOverviewList[i] > 0 )
    00260             panNewOverviewList[nNewOverviews++] = panOverviewList[i];
    00261     }
    00262
    00263 /* -------------------------------------------------------------------- */
    00264 /*      If we have an existing overview file open, close it now.        */
    00265 /* -------------------------------------------------------------------- */
    00266     if( poODS != NULL )
    00267     {
    00268         delete poODS;
    00269         poODS = NULL;
    00270     }
    00271
    00272 /* -------------------------------------------------------------------- */
    00273 /*      Build band list.                                                */
    00274 /* -------------------------------------------------------------------- */
    00275     pahBands = (GDALRasterBand **) CPLCalloc(sizeof(GDALRasterBand *),nBands);
    00276     for( i = 0; i < nBands; i++ )
    00277         pahBands[i] = poDS->GetRasterBand( panBandList[i] );
    00278
    00279 /* -------------------------------------------------------------------- */
    00280 /*      Build new overviews.                                            */
    00281 /* -------------------------------------------------------------------- */
    00282
    00283     eErr = GTIFFBuildOverviews( pszOvrFilename, nBands, pahBands,
    00284                                 nNewOverviews, panNewOverviewList,
    00285                                 pszResampling, pfnProgress, pProgressData );
    00286
    00287 /* -------------------------------------------------------------------- */
    00288 /*      Refresh old overviews that were listed.                         */
    00289 /* -------------------------------------------------------------------- */
    00290     GDALRasterBand **papoOverviewBands;
    00291
    00292     if( eErr == CE_None )
    00293     {
    00294         poODS = (GDALDataset *) GDALOpen( pszOvrFilename, GA_Update );
    00295         if( poODS == NULL )
    00296             eErr = CE_Failure;
    00297     }
    00298
    00299     papoOverviewBands = (GDALRasterBand **)
    00300         CPLCalloc(sizeof(void*),nOverviews);
    00301
    00302     for( int iBand = 0; iBand < nBands && eErr == CE_None; iBand++ )
    00303     {
    00304         poBand = poDS->GetRasterBand( panBandList[iBand] );
    00305
    00306         nNewOverviews = 0;
    00307         for( i = 0; i < nOverviews && poBand != NULL; i++ )
    00308         {
    00309             int   j;
    00310
    00311             for( j = 0; j < poBand->GetOverviewCount(); j++ )
    00312             {
    00313                 int    nOvFactor;
    00314                 GDALRasterBand * poOverview = poBand->GetOverview( j );
    00315
    00316                 nOvFactor = (int)
    00317                     (0.5 + poBand->GetXSize() / (double) poOverview->GetXSize());
    00318
    00319                 if( nOvFactor == - panOverviewList[i]
    00320                     || nOvFactor == GDALOvLevelAdjust( -panOverviewList[i],
    00321                                                        poBand->GetXSize() ) )
    00322                 {
    00323                     panOverviewList[i] *= -1;
    00324                     papoOverviewBands[nNewOverviews++] = poOverview;
    00325                 }
    00326             }
    00327         }
    00328
    00329         if( nNewOverviews > 0 )
    00330         {
    00331             eErr = GDALRegenerateOverviews( poBand,
    00332                                             nNewOverviews, papoOverviewBands,
    00333                                             pszResampling,
    00334                                             GDALDummyProgress, NULL );
    00335         }
    00336     }
    00337
    00338 /* -------------------------------------------------------------------- */
    00339 /*      Cleanup                                                         */
    00340 /* -------------------------------------------------------------------- */
    00341     CPLFree( papoOverviewBands );
    00342     CPLFree( panNewOverviewList );
    00343     CPLFree( pahBands );
    00344
    00345     return eErr;
    00346 }
    00347