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 

Generated at Thu Mar 28 09:47:30 2002 for GDAL by doxygen1.2.3-20001105 written by Dimitri van Heesch, © 1997-2000