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