00001 /****************************************************************************** 00002 * $Id: gdaldefaultoverviews_cpp-source.html,v 1.8 2001/07/05 13:24:08 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.8 2001/07/05 13:24:08 warmerda 00030 * *** empty log message *** 00030 * 00031 * Revision 1.6 2001/06/22 21:00:38 warmerda 00032 * fixed several problems with regenerating existing overviews 00033 * 00034 * Revision 1.5 2001/06/22 13:52:03 warmerda 00035 * fixed bug when refreshing overviews during build 00036 * 00037 * Revision 1.4 2001/06/20 16:08:54 warmerda 00038 * GDALDefaultOverviews now remembers ovr filename, and allows explicit setting 00039 * 00040 * Revision 1.3 2000/06/19 18:48:49 warmerda 00041 * fixed message 00042 * 00043 * Revision 1.2 2000/06/19 14:42:27 warmerda 00044 * Don't close old overviews till after we have identified which already 00045 * exist, otherwise multiple copies of overviews may be created. 00046 * 00047 * Revision 1.1 2000/04/21 21:54:05 warmerda 00048 * New 00049 * 00050 */ 00051 00052 #include "gdal_priv.h" 00053 00054 /************************************************************************/ 00055 /* GDALDefaultOverviews() */ 00056 /************************************************************************/ 00057 00058 GDALDefaultOverviews::GDALDefaultOverviews() 00059 00060 { 00061 poDS = NULL; 00062 poODS = NULL; 00063 pszOvrFilename = NULL; 00064 } 00065 00066 /************************************************************************/ 00067 /* ~GDALDefaultOverviews() */ 00068 /************************************************************************/ 00069 00070 GDALDefaultOverviews::~GDALDefaultOverviews() 00071 00072 { 00073 if( poODS != NULL ) 00074 { 00075 poODS->FlushCache(); 00076 delete poODS; 00077 } 00078 CPLFree( pszOvrFilename ); 00079 } 00080 00081 /************************************************************************/ 00082 /* Initialize() */ 00083 /************************************************************************/ 00084 00085 void GDALDefaultOverviews::Initialize( GDALDataset *poDS, 00086 const char * pszBasename, 00087 int bNameIsOVR ) 00088 00089 { 00090 VSIStatBuf sStatBuf; 00091 00092 /* -------------------------------------------------------------------- */ 00093 /* If we were already initialized, destroy the old overview */ 00094 /* file handle. */ 00095 /* -------------------------------------------------------------------- */ 00096 if( this->poODS != NULL ) 00097 { 00098 delete poODS; 00099 } 00100 00101 /* -------------------------------------------------------------------- */ 00102 /* Open overview dataset if it exists. */ 00103 /* -------------------------------------------------------------------- */ 00104 this->poDS = poDS; 00105 00106 if( pszBasename == NULL ) 00107 pszBasename = poDS->GetDescription(); 00108 00109 CPLFree( pszOvrFilename ); 00110 pszOvrFilename = (char *) CPLMalloc(strlen(pszBasename)+5); 00111 if( bNameIsOVR ) 00112 strcpy( pszOvrFilename, pszBasename ); 00113 else 00114 sprintf( pszOvrFilename, "%s.ovr", pszBasename ); 00115 00116 if( VSIStat( pszOvrFilename, &sStatBuf ) == 0 ) 00117 poODS = (GDALDataset *) GDALOpen( pszOvrFilename, poDS->GetAccess() ); 00118 } 00119 00120 /************************************************************************/ 00121 /* GetOverviewCount() */ 00122 /************************************************************************/ 00123 00124 int GDALDefaultOverviews::GetOverviewCount( int nBand ) 00125 00126 { 00127 GDALRasterBand * poBand; 00128 00129 if( poODS == NULL || nBand < 1 || nBand > poODS->GetRasterCount() ) 00130 return 0; 00131 00132 poBand = poODS->GetRasterBand( nBand ); 00133 if( poBand == NULL ) 00134 return 0; 00135 else 00136 return poBand->GetOverviewCount() + 1; 00137 } 00138 00139 /************************************************************************/ 00140 /* GetOverview() */ 00141 /************************************************************************/ 00142 00143 GDALRasterBand * 00144 GDALDefaultOverviews::GetOverview( int nBand, int iOverview ) 00145 00146 { 00147 GDALRasterBand * poBand; 00148 00149 if( poODS == NULL || nBand < 1 || nBand > poODS->GetRasterCount() ) 00150 return NULL; 00151 00152 poBand = poODS->GetRasterBand( nBand ); 00153 if( poBand == NULL ) 00154 return NULL; 00155 00156 if( iOverview == 0 ) 00157 return poBand; 00158 else if( iOverview-1 >= poBand->GetOverviewCount() ) 00159 return NULL; 00160 else 00161 return poBand->GetOverview( iOverview-1 ); 00162 } 00163 00164 /************************************************************************/ 00165 /* GDALOvLevelAdjust() */ 00166 /* */ 00167 /* Some overview levels cannot be achieved closely enough to be */ 00168 /* recognised as the desired overview level. This function */ 00169 /* will adjust an overview level to one that is achievable on */ 00170 /* the given raster size. */ 00171 /* */ 00172 /* For instance a 1200x1200 image on which a 256 level overview */ 00173 /* is request will end up generating a 5x5 overview. However, */ 00174 /* this will appear to the system be a level 240 overview. */ 00175 /* This function will adjust 256 to 240 based on knowledge of */ 00176 /* the image size. */ 00177 /************************************************************************/ 00178 00179 static int GDALOvLevelAdjust( int nOvLevel, int nXSize ) 00180 00181 { 00182 int nOXSize = (nXSize + nOvLevel - 1) / nOvLevel; 00183 00184 return (int) (0.5 + nXSize / (double) nOXSize); 00185 } 00186 00187 /************************************************************************/ 00188 /* GDALDefaultBuildOverviews() */ 00189 /************************************************************************/ 00190 00191 CPLErr 00192 GDALDefaultOverviews::BuildOverviews( 00193 const char * pszBasename, 00194 const char * pszResampling, 00195 int nOverviews, int * panOverviewList, 00196 int nBands, int * panBandList, 00197 GDALProgressFunc pfnProgress, void * pProgressData) 00198 00199 { 00200 GDALRasterBand **pahBands; 00201 CPLErr eErr; 00202 int i; 00203 00204 /* -------------------------------------------------------------------- */ 00205 /* Our TIFF overview support currently only works safely if all */ 00206 /* bands are handled at the same time. */ 00207 /* -------------------------------------------------------------------- */ 00208 if( nBands != poDS->GetRasterCount() ) 00209 { 00210 CPLError( CE_Failure, CPLE_NotSupported, 00211 "Generation of overviews in external TIFF currently only" 00212 " supported when operating on all bands.\n" 00213 "Operation failed.\n" ); 00214 return CE_Failure; 00215 } 00216 00217 /* -------------------------------------------------------------------- */ 00218 /* If a basename is provided, use it to override the internal */ 00219 /* overview filename. */ 00220 /* -------------------------------------------------------------------- */ 00221 if( pszBasename == NULL && pszOvrFilename == NULL ) 00222 pszBasename = poDS->GetDescription(); 00223 00224 if( pszBasename != NULL ) 00225 { 00226 CPLFree( pszOvrFilename ); 00227 pszOvrFilename = (char *) CPLMalloc(strlen(pszBasename)+5); 00228 sprintf( pszOvrFilename, "%s.ovr", pszBasename ); 00229 } 00230 00231 /* -------------------------------------------------------------------- */ 00232 /* Establish which of the overview levels we already have, and */ 00233 /* which are new. We assume that band 1 of the file is */ 00234 /* representative. */ 00235 /* -------------------------------------------------------------------- */ 00236 int nNewOverviews, *panNewOverviewList = NULL; 00237 GDALRasterBand *poBand = poDS->GetRasterBand( 1 ); 00238 00239 nNewOverviews = 0; 00240 panNewOverviewList = (int *) CPLCalloc(sizeof(int),nOverviews); 00241 for( i = 0; i < nOverviews && poBand != NULL; i++ ) 00242 { 00243 int j; 00244 00245 for( j = 0; j < poBand->GetOverviewCount(); j++ ) 00246 { 00247 int nOvFactor; 00248 GDALRasterBand * poOverview = poBand->GetOverview( j ); 00249 00250 nOvFactor = (int) 00251 (0.5 + poBand->GetXSize() / (double) poOverview->GetXSize()); 00252 00253 if( nOvFactor == panOverviewList[i] 00254 || nOvFactor == GDALOvLevelAdjust( panOverviewList[i], 00255 poBand->GetXSize() ) ) 00256 panOverviewList[i] *= -1; 00257 } 00258 00259 if( panOverviewList[i] > 0 ) 00260 panNewOverviewList[nNewOverviews++] = panOverviewList[i]; 00261 } 00262 00263 /* -------------------------------------------------------------------- */ 00264 /* If we have an existing overview file open, close it now. */ 00265 /* -------------------------------------------------------------------- */ 00266 if( poODS != NULL ) 00267 { 00268 delete poODS; 00269 poODS = NULL; 00270 } 00271 00272 /* -------------------------------------------------------------------- */ 00273 /* Build band list. */ 00274 /* -------------------------------------------------------------------- */ 00275 pahBands = (GDALRasterBand **) CPLCalloc(sizeof(GDALRasterBand *),nBands); 00276 for( i = 0; i < nBands; i++ ) 00277 pahBands[i] = poDS->GetRasterBand( panBandList[i] ); 00278 00279 /* -------------------------------------------------------------------- */ 00280 /* Build new overviews. */ 00281 /* -------------------------------------------------------------------- */ 00282 00283 eErr = GTIFFBuildOverviews( pszOvrFilename, nBands, pahBands, 00284 nNewOverviews, panNewOverviewList, 00285 pszResampling, pfnProgress, pProgressData ); 00286 00287 /* -------------------------------------------------------------------- */ 00288 /* Refresh old overviews that were listed. */ 00289 /* -------------------------------------------------------------------- */ 00290 GDALRasterBand **papoOverviewBands; 00291 00292 if( eErr == CE_None ) 00293 { 00294 poODS = (GDALDataset *) GDALOpen( pszOvrFilename, GA_Update ); 00295 if( poODS == NULL ) 00296 eErr = CE_Failure; 00297 } 00298 00299 papoOverviewBands = (GDALRasterBand **) 00300 CPLCalloc(sizeof(void*),nOverviews); 00301 00302 for( int iBand = 0; iBand < nBands && eErr == CE_None; iBand++ ) 00303 { 00304 poBand = poDS->GetRasterBand( panBandList[iBand] ); 00305 00306 nNewOverviews = 0; 00307 for( i = 0; i < nOverviews && poBand != NULL; i++ ) 00308 { 00309 int j; 00310 00311 for( j = 0; j < poBand->GetOverviewCount(); j++ ) 00312 { 00313 int nOvFactor; 00314 GDALRasterBand * poOverview = poBand->GetOverview( j ); 00315 00316 nOvFactor = (int) 00317 (0.5 + poBand->GetXSize() / (double) poOverview->GetXSize()); 00318 00319 if( nOvFactor == - panOverviewList[i] 00320 || nOvFactor == GDALOvLevelAdjust( -panOverviewList[i], 00321 poBand->GetXSize() ) ) 00322 { 00323 panOverviewList[i] *= -1; 00324 papoOverviewBands[nNewOverviews++] = poOverview; 00325 } 00326 } 00327 } 00328 00329 if( nNewOverviews > 0 ) 00330 { 00331 eErr = GDALRegenerateOverviews( poBand, 00332 nNewOverviews, papoOverviewBands, 00333 pszResampling, 00334 GDALDummyProgress, NULL ); 00335 } 00336 } 00337 00338 /* -------------------------------------------------------------------- */ 00339 /* Cleanup */ 00340 /* -------------------------------------------------------------------- */ 00341 CPLFree( papoOverviewBands ); 00342 CPLFree( panNewOverviewList ); 00343 CPLFree( pahBands ); 00344 00345 return eErr; 00346 } 00347