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.10 2002/04/16 13:11:48 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.10  2002/04/16 13:11:48  warmerda
    00030  * updated
    00030  *
    00031  * Revision 1.8  2001/10/18 14:35:22  warmerda
    00032  * avoid conflicts between parameters and member data
    00033  *
    00034  * Revision 1.7  2001/07/18 04:04:30  warmerda
    00035  * added CPL_CVSID
    00036  *
    00037  * Revision 1.6  2001/06/22 21:00:38  warmerda
    00038  * fixed several problems with regenerating existing overviews
    00039  *
    00040  * Revision 1.5  2001/06/22 13:52:03  warmerda
    00041  * fixed bug when refreshing overviews during build
    00042  *
    00043  * Revision 1.4  2001/06/20 16:08:54  warmerda
    00044  * GDALDefaultOverviews now remembers ovr filename, and allows explicit setting
    00045  *
    00046  * Revision 1.3  2000/06/19 18:48:49  warmerda
    00047  * fixed message
    00048  *
    00049  * Revision 1.2  2000/06/19 14:42:27  warmerda
    00050  * Don't close old overviews till after we have identified which already
    00051  * exist, otherwise multiple copies of overviews may be created.
    00052  *
    00053  * Revision 1.1  2000/04/21 21:54:05  warmerda
    00054  * New
    00055  *
    00056  */
    00057
    00058 #include "gdal_priv.h"
    00059
    00060 CPL_CVSID("$Id: gdaldefaultoverviews_cpp-source.html,v 1.10 2002/04/16 13:11:48 warmerda Exp $");
    00061
    00062 /************************************************************************/
    00063 /*                        GDALDefaultOverviews()                        */
    00064 /************************************************************************/
    00065
    00066 GDALDefaultOverviews::GDALDefaultOverviews()
    00067
    00068 {
    00069     poDS = NULL;
    00070     poODS = NULL;
    00071     pszOvrFilename = NULL;
    00072 }
    00073
    00074 /************************************************************************/
    00075 /*                       ~GDALDefaultOverviews()                        */
    00076 /************************************************************************/
    00077
    00078 GDALDefaultOverviews::~GDALDefaultOverviews()
    00079
    00080 {
    00081     if( poODS != NULL )
    00082     {
    00083         poODS->FlushCache();
    00084         delete poODS;
    00085     }
    00086     CPLFree( pszOvrFilename );
    00087 }
    00088
    00089 /************************************************************************/
    00090 /*                             Initialize()                             */
    00091 /************************************************************************/
    00092
    00093 void GDALDefaultOverviews::Initialize( GDALDataset *poDSIn,
    00094                                        const char * pszBasename,
    00095                                        int bNameIsOVR )
    00096
    00097 {
    00098     VSIStatBuf sStatBuf;
    00099
    00100 /* -------------------------------------------------------------------- */
    00101 /*      If we were already initialized, destroy the old overview        */
    00102 /*      file handle.                                                    */
    00103 /* -------------------------------------------------------------------- */
    00104     if( poODS != NULL )
    00105     {
    00106         delete poODS;
    00107     }
    00108
    00109 /* -------------------------------------------------------------------- */
    00110 /*      Open overview dataset if it exists.                             */
    00111 /* -------------------------------------------------------------------- */
    00112     poDS = poDSIn;
    00113
    00114     if( pszBasename == NULL )
    00115         pszBasename = poDS->GetDescription();
    00116
    00117     CPLFree( pszOvrFilename );
    00118     pszOvrFilename = (char *) CPLMalloc(strlen(pszBasename)+5);
    00119     if( bNameIsOVR )
    00120         strcpy( pszOvrFilename, pszBasename );
    00121     else
    00122         sprintf( pszOvrFilename, "%s.ovr", pszBasename );
    00123
    00124     if( VSIStat( pszOvrFilename, &sStatBuf ) == 0 )
    00125         poODS = (GDALDataset *) GDALOpen( pszOvrFilename, poDS->GetAccess() );
    00126 }
    00127
    00128 /************************************************************************/
    00129 /*                          GetOverviewCount()                          */
    00130 /************************************************************************/
    00131
    00132 int GDALDefaultOverviews::GetOverviewCount( int nBand )
    00133
    00134 {
    00135     GDALRasterBand * poBand;
    00136
    00137     if( poODS == NULL || nBand < 1 || nBand > poODS->GetRasterCount() )
    00138         return 0;
    00139
    00140     poBand = poODS->GetRasterBand( nBand );
    00141     if( poBand == NULL )
    00142         return 0;
    00143     else
    00144         return poBand->GetOverviewCount() + 1;
    00145 }
    00146
    00147 /************************************************************************/
    00148 /*                            GetOverview()                             */
    00149 /************************************************************************/
    00150
    00151 GDALRasterBand *
    00152 GDALDefaultOverviews::GetOverview( int nBand, int iOverview )
    00153
    00154 {
    00155     GDALRasterBand * poBand;
    00156
    00157     if( poODS == NULL || nBand < 1 || nBand > poODS->GetRasterCount() )
    00158         return NULL;
    00159
    00160     poBand = poODS->GetRasterBand( nBand );
    00161     if( poBand == NULL )
    00162         return NULL;
    00163
    00164     if( iOverview == 0 )
    00165         return poBand;
    00166     else if( iOverview-1 >= poBand->GetOverviewCount() )
    00167         return NULL;
    00168     else
    00169         return poBand->GetOverview( iOverview-1 );
    00170 }
    00171
    00172 /************************************************************************/
    00173 /*                         GDALOvLevelAdjust()                          */
    00174 /*                                                                      */
    00175 /*      Some overview levels cannot be achieved closely enough to be    */
    00176 /*      recognised as the desired overview level.  This function        */
    00177 /*      will adjust an overview level to one that is achievable on      */
    00178 /*      the given raster size.                                          */
    00179 /*                                                                      */
    00180 /*      For instance a 1200x1200 image on which a 256 level overview    */
    00181 /*      is request will end up generating a 5x5 overview.  However,     */
    00182 /*      this will appear to the system be a level 240 overview.         */
    00183 /*      This function will adjust 256 to 240 based on knowledge of      */
    00184 /*      the image size.                                                 */
    00185 /************************************************************************/
    00186
    00187 static int GDALOvLevelAdjust( int nOvLevel, int nXSize )
    00188
    00189 {
    00190     int nOXSize = (nXSize + nOvLevel - 1) / nOvLevel;
    00191
    00192     return (int) (0.5 + nXSize / (double) nOXSize);
    00193 }
    00194
    00195 /************************************************************************/
    00196 /*                     GDALDefaultBuildOverviews()                      */
    00197 /************************************************************************/
    00198
    00199 CPLErr
    00200 GDALDefaultOverviews::BuildOverviews(
    00201     const char * pszBasename,
    00202     const char * pszResampling,
    00203     int nOverviews, int * panOverviewList,
    00204     int nBands, int * panBandList,
    00205     GDALProgressFunc pfnProgress, void * pProgressData)
    00206
    00207 {
    00208     GDALRasterBand **pahBands;
    00209     CPLErr       eErr;
    00210     int          i;
    00211
    00212 /* -------------------------------------------------------------------- */
    00213 /*      Our TIFF overview support currently only works safely if all    */
    00214 /*      bands are handled at the same time.                             */
    00215 /* -------------------------------------------------------------------- */
    00216     if( nBands != poDS->GetRasterCount() )
    00217     {
    00218         CPLError( CE_Failure, CPLE_NotSupported,
    00219                   "Generation of overviews in external TIFF currently only"
    00220                   " supported when operating on all bands.\n"
    00221                   "Operation failed.\n" );
    00222         return CE_Failure;
    00223     }
    00224
    00225 /* -------------------------------------------------------------------- */
    00226 /*      If a basename is provided, use it to override the internal      */
    00227 /*      overview filename.                                              */
    00228 /* -------------------------------------------------------------------- */
    00229     if( pszBasename == NULL && pszOvrFilename == NULL )
    00230         pszBasename = poDS->GetDescription();
    00231
    00232     if( pszBasename != NULL )
    00233     {
    00234         CPLFree( pszOvrFilename );
    00235         pszOvrFilename = (char *) CPLMalloc(strlen(pszBasename)+5);
    00236         sprintf( pszOvrFilename, "%s.ovr", pszBasename );
    00237     }
    00238
    00239 /* -------------------------------------------------------------------- */
    00240 /*      Establish which of the overview levels we already have, and     */
    00241 /*      which are new.  We assume that band 1 of the file is            */
    00242 /*      representative.                                                 */
    00243 /* -------------------------------------------------------------------- */
    00244     int   nNewOverviews, *panNewOverviewList = NULL;
    00245     GDALRasterBand *poBand = poDS->GetRasterBand( 1 );
    00246
    00247     nNewOverviews = 0;
    00248     panNewOverviewList = (int *) CPLCalloc(sizeof(int),nOverviews);
    00249     for( i = 0; i < nOverviews && poBand != NULL; i++ )
    00250     {
    00251         int   j;
    00252
    00253         for( j = 0; j < poBand->GetOverviewCount(); j++ )
    00254         {
    00255             int    nOvFactor;
    00256             GDALRasterBand * poOverview = poBand->GetOverview( j );
    00257
    00258             nOvFactor = (int)
    00259                 (0.5 + poBand->GetXSize() / (double) poOverview->GetXSize());
    00260
    00261             if( nOvFactor == panOverviewList[i]
    00262                 || nOvFactor == GDALOvLevelAdjust( panOverviewList[i],
    00263                                                    poBand->GetXSize() ) )
    00264                 panOverviewList[i] *= -1;
    00265         }
    00266
    00267         if( panOverviewList[i] > 0 )
    00268             panNewOverviewList[nNewOverviews++] = panOverviewList[i];
    00269     }
    00270
    00271 /* -------------------------------------------------------------------- */
    00272 /*      If we have an existing overview file open, close it now.        */
    00273 /* -------------------------------------------------------------------- */
    00274     if( poODS != NULL )
    00275     {
    00276         delete poODS;
    00277         poODS = NULL;
    00278     }
    00279
    00280 /* -------------------------------------------------------------------- */
    00281 /*      Build band list.                                                */
    00282 /* -------------------------------------------------------------------- */
    00283     pahBands = (GDALRasterBand **) CPLCalloc(sizeof(GDALRasterBand *),nBands);
    00284     for( i = 0; i < nBands; i++ )
    00285         pahBands[i] = poDS->GetRasterBand( panBandList[i] );
    00286
    00287 /* -------------------------------------------------------------------- */
    00288 /*      Build new overviews.                                            */
    00289 /* -------------------------------------------------------------------- */
    00290
    00291     eErr = GTIFFBuildOverviews( pszOvrFilename, nBands, pahBands,
    00292                                 nNewOverviews, panNewOverviewList,
    00293                                 pszResampling, pfnProgress, pProgressData );
    00294
    00295 /* -------------------------------------------------------------------- */
    00296 /*      Refresh old overviews that were listed.                         */
    00297 /* -------------------------------------------------------------------- */
    00298     GDALRasterBand **papoOverviewBands;
    00299
    00300     if( eErr == CE_None )
    00301     {
    00302         poODS = (GDALDataset *) GDALOpen( pszOvrFilename, GA_Update );
    00303         if( poODS == NULL )
    00304             eErr = CE_Failure;
    00305     }
    00306
    00307     papoOverviewBands = (GDALRasterBand **)
    00308         CPLCalloc(sizeof(void*),nOverviews);
    00309
    00310     for( int iBand = 0; iBand < nBands && eErr == CE_None; iBand++ )
    00311     {
    00312         poBand = poDS->GetRasterBand( panBandList[iBand] );
    00313
    00314         nNewOverviews = 0;
    00315         for( i = 0; i < nOverviews && poBand != NULL; i++ )
    00316         {
    00317             int   j;
    00318
    00319             for( j = 0; j < poBand->GetOverviewCount(); j++ )
    00320             {
    00321                 int    nOvFactor;
    00322                 GDALRasterBand * poOverview = poBand->GetOverview( j );
    00323
    00324                 nOvFactor = (int)
    00325                     (0.5 + poBand->GetXSize() / (double) poOverview->GetXSize());
    00326
    00327                 if( nOvFactor == - panOverviewList[i]
    00328                     || nOvFactor == GDALOvLevelAdjust( -panOverviewList[i],
    00329                                                        poBand->GetXSize() ) )
    00330                 {
    00331                     panOverviewList[i] *= -1;
    00332                     papoOverviewBands[nNewOverviews++] = poOverview;
    00333                 }
    00334             }
    00335         }
    00336
    00337         if( nNewOverviews > 0 )
    00338         {
    00339             eErr = GDALRegenerateOverviews( poBand,
    00340                                             nNewOverviews, papoOverviewBands,
    00341                                             pszResampling,
    00342                                             GDALDummyProgress, NULL );
    00343         }
    00344     }
    00345
    00346 /* -------------------------------------------------------------------- */
    00347 /*      Cleanup                                                         */
    00348 /* -------------------------------------------------------------------- */
    00349     CPLFree( papoOverviewBands );
    00350     CPLFree( panNewOverviewList );
    00351     CPLFree( pahBands );
    00352
    00353     return eErr;
    00354 }
    00355