00001 /****************************************************************************** 00002 * $Id: gdaldefaultoverviews_cpp-source.html,v 1.5 2000/11/06 04:49:01 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.5 2000/11/06 04:49:01 warmerda 00030 * *** empty log message *** 00030 * 00031 * Revision 1.3 2000/06/19 18:48:49 warmerda 00032 * fixed message 00033 * 00034 * Revision 1.2 2000/06/19 14:42:27 warmerda 00035 * Don't close old overviews till after we have identified which already 00036 * exist, otherwise multiple copies of overviews may be created. 00037 * 00038 * Revision 1.1 2000/04/21 21:54:05 warmerda 00039 * New 00040 * 00041 */ 00042 00043 #include "gdal_priv.h" 00044 00045 /************************************************************************/ 00046 /* GDALDefaultOverviews() */ 00047 /************************************************************************/ 00048 00049 GDALDefaultOverviews::GDALDefaultOverviews() 00050 00051 { 00052 poDS = NULL; 00053 poODS = NULL; 00054 } 00055 00056 /************************************************************************/ 00057 /* ~GDALDefaultOverviews() */ 00058 /************************************************************************/ 00059 00060 GDALDefaultOverviews::~GDALDefaultOverviews() 00061 00062 { 00063 if( poODS != NULL ) 00064 { 00065 poODS->FlushCache(); 00066 delete poODS; 00067 } 00068 } 00069 00070 /************************************************************************/ 00071 /* Initialize() */ 00072 /************************************************************************/ 00073 00074 void GDALDefaultOverviews::Initialize( GDALDataset *poDS, 00075 const char * pszBasename ) 00076 00077 { 00078 char * pszTIFFFilename; 00079 VSIStatBuf sStatBuf; 00080 00081 /* -------------------------------------------------------------------- */ 00082 /* If we were already initialized, destroy the old overview */ 00083 /* file handle. */ 00084 /* -------------------------------------------------------------------- */ 00085 if( this->poODS != NULL ) 00086 { 00087 delete poODS; 00088 } 00089 00090 /* -------------------------------------------------------------------- */ 00091 /* Open overview dataset if it exists. */ 00092 /* -------------------------------------------------------------------- */ 00093 this->poDS = poDS; 00094 00095 if( pszBasename == NULL ) 00096 pszBasename = poDS->GetDescription(); 00097 00098 pszTIFFFilename = (char *) CPLMalloc(strlen(pszBasename)+5); 00099 sprintf( pszTIFFFilename, "%s.ovr", pszBasename ); 00100 00101 if( VSIStat( pszTIFFFilename, &sStatBuf ) == 0 ) 00102 poODS = (GDALDataset *) GDALOpen( pszTIFFFilename, poDS->GetAccess() ); 00103 00104 CPLFree( pszTIFFFilename ); 00105 } 00106 00107 /************************************************************************/ 00108 /* GetOverviewCount() */ 00109 /************************************************************************/ 00110 00111 int GDALDefaultOverviews::GetOverviewCount( int nBand ) 00112 00113 { 00114 GDALRasterBand * poBand; 00115 00116 if( poODS == NULL || nBand < 1 || nBand > poODS->GetRasterCount() ) 00117 return 0; 00118 00119 poBand = poODS->GetRasterBand( nBand ); 00120 if( poBand == NULL ) 00121 return 0; 00122 else 00123 return poBand->GetOverviewCount() + 1; 00124 } 00125 00126 /************************************************************************/ 00127 /* GetOverview() */ 00128 /************************************************************************/ 00129 00130 GDALRasterBand * 00131 GDALDefaultOverviews::GetOverview( int nBand, int iOverview ) 00132 00133 { 00134 GDALRasterBand * poBand; 00135 00136 if( poODS == NULL || nBand < 1 || nBand > poODS->GetRasterCount() ) 00137 return NULL; 00138 00139 poBand = poODS->GetRasterBand( nBand ); 00140 if( poBand == NULL ) 00141 return NULL; 00142 00143 if( iOverview == 0 ) 00144 return poBand; 00145 else if( iOverview-1 >= poBand->GetOverviewCount() ) 00146 return NULL; 00147 else 00148 return poBand->GetOverview( iOverview-1 ); 00149 } 00150 00151 /************************************************************************/ 00152 /* GDALDefaultBuildOverviews() */ 00153 /************************************************************************/ 00154 00155 CPLErr 00156 GDALDefaultOverviews::BuildOverviews( 00157 const char * pszBasename, 00158 const char * pszResampling, 00159 int nOverviews, int * panOverviewList, 00160 int nBands, int * panBandList, 00161 GDALProgressFunc pfnProgress, void * pProgressData) 00162 00163 { 00164 char * pszTIFFFilename; 00165 GDALRasterBand **pahBands; 00166 CPLErr eErr; 00167 int i; 00168 00169 /* -------------------------------------------------------------------- */ 00170 /* Our TIFF overview support currently only works safely if all */ 00171 /* bands are handled at the same time. */ 00172 /* -------------------------------------------------------------------- */ 00173 if( nBands != poDS->GetRasterCount() ) 00174 { 00175 CPLError( CE_Failure, CPLE_NotSupported, 00176 "Generation of overviews in external TIFF currently only" 00177 " supported when operating on all bands.\n" 00178 "Operation failed.\n" ); 00179 return CE_Failure; 00180 } 00181 00182 /* -------------------------------------------------------------------- */ 00183 /* By default we assume that the dataset name is a suitable */ 00184 /* filesystem object to associate with if nothing is provided. */ 00185 /* -------------------------------------------------------------------- */ 00186 if( pszBasename == NULL ) 00187 pszBasename = poDS->GetDescription(); 00188 00189 /* -------------------------------------------------------------------- */ 00190 /* Generate the TIFF filename. This approach may not work well */ 00191 /* on Windows. */ 00192 /* -------------------------------------------------------------------- */ 00193 pszTIFFFilename = (char *) CPLMalloc(strlen(pszBasename)+5); 00194 sprintf( pszTIFFFilename, "%s.ovr", pszBasename ); 00195 00196 /* -------------------------------------------------------------------- */ 00197 /* Establish which of the overview levels we already have, and */ 00198 /* which are new. We assume that band 1 of the file is */ 00199 /* representative. */ 00200 /* -------------------------------------------------------------------- */ 00201 int nNewOverviews, *panNewOverviewList = NULL; 00202 GDALRasterBand *poBand = poDS->GetRasterBand( 1 ); 00203 00204 nNewOverviews = 0; 00205 panNewOverviewList = (int *) CPLCalloc(sizeof(int),nOverviews); 00206 for( i = 0; i < nOverviews && poBand != NULL; i++ ) 00207 { 00208 int j; 00209 00210 for( j = 0; j < poBand->GetOverviewCount(); j++ ) 00211 { 00212 int nOvFactor; 00213 GDALRasterBand * poOverview = poBand->GetOverview( j ); 00214 00215 nOvFactor = (int) 00216 (0.5 + poBand->GetXSize() / (double) poOverview->GetXSize()); 00217 00218 if( nOvFactor == panOverviewList[i] ) 00219 panOverviewList[i] *= -1; 00220 } 00221 00222 if( panOverviewList[i] > 0 ) 00223 panNewOverviewList[nNewOverviews++] = panOverviewList[i]; 00224 } 00225 00226 /* -------------------------------------------------------------------- */ 00227 /* If we have an existing overview file open, close it now. */ 00228 /* -------------------------------------------------------------------- */ 00229 if( poODS != NULL ) 00230 { 00231 delete poODS; 00232 poODS = NULL; 00233 } 00234 00235 /* -------------------------------------------------------------------- */ 00236 /* Build band list. */ 00237 /* -------------------------------------------------------------------- */ 00238 pahBands = (GDALRasterBand **) CPLCalloc(sizeof(GDALRasterBand *),nBands); 00239 for( i = 0; i < nBands; i++ ) 00240 pahBands[i] = poDS->GetRasterBand( panBandList[i] ); 00241 00242 /* -------------------------------------------------------------------- */ 00243 /* Build new overviews. */ 00244 /* -------------------------------------------------------------------- */ 00245 00246 eErr = GTIFFBuildOverviews( pszTIFFFilename, nBands, pahBands, 00247 nNewOverviews, panNewOverviewList, 00248 pszResampling, pfnProgress, pProgressData ); 00249 00250 /* -------------------------------------------------------------------- */ 00251 /* Refresh old overviews that were listed. */ 00252 /* -------------------------------------------------------------------- */ 00253 GDALRasterBand **papoOverviewBands; 00254 00255 if( eErr == CE_None ) 00256 { 00257 poODS = (GDALDataset *) GDALOpen( pszTIFFFilename, GA_Update ); 00258 if( poODS == NULL ) 00259 eErr = CE_Failure; 00260 } 00261 00262 papoOverviewBands = (GDALRasterBand **) 00263 CPLCalloc(sizeof(void*),nOverviews); 00264 00265 for( int iBand = 0; iBand < nBands && eErr == CE_None; iBand++ ) 00266 { 00267 poBand = poDS->GetRasterBand( panBandList[iBand] ); 00268 00269 nNewOverviews = 0; 00270 for( i = 0; i < nOverviews && poBand != NULL; i++ ) 00271 { 00272 int j; 00273 00274 for( j = 0; j < poBand->GetOverviewCount(); j++ ) 00275 { 00276 int nOvFactor; 00277 GDALRasterBand * poOverview = poBand->GetOverview( j ); 00278 00279 nOvFactor = (int) 00280 (0.5 + poBand->GetXSize() / (double) poOverview->GetXSize()); 00281 00282 if( nOvFactor == -1 * panOverviewList[i] ) 00283 { 00284 panOverviewList[i] *= -1; 00285 papoOverviewBands[nNewOverviews++] = poBand; 00286 } 00287 } 00288 } 00289 00290 if( nNewOverviews > 0 ) 00291 { 00292 eErr = GDALRegenerateOverviews( poBand, 00293 nNewOverviews, papoOverviewBands, 00294 pszResampling, NULL, NULL ); 00295 } 00296 } 00297 00298 /* -------------------------------------------------------------------- */ 00299 /* Cleanup */ 00300 /* -------------------------------------------------------------------- */ 00301 CPLFree( papoOverviewBands ); 00302 CPLFree( panNewOverviewList ); 00303 CPLFree( pahBands ); 00304 CPLFree( pszTIFFFilename ); 00305 00306 return eErr; 00307 } 00308