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