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 

Generated at Sat Dec 21 14:01:59 2002 for GDAL by doxygen1.2.3-20001105 written by Dimitri van Heesch, © 1997-2000