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