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
1.2.3-20001105 written by Dimitri van Heesch,
© 1997-2000