root/tags/gdal_1_3_2/gcore/gdaldefaultoverviews.cpp

Revision 9397, 17.3 kB (checked in by fwarmerdam, 3 years ago)

reopen overview file in update mode if needed when building overviews

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /******************************************************************************
2  * $Id$
3  *
4  * Project:  GDAL Core
5  * Purpose:  Helper code to implement overview support in different drivers.
6  * Author:   Frank Warmerdam, warmerdam@pobox.com
7  *
8  ******************************************************************************
9  * Copyright (c) 2000, Frank Warmerdam
10  *
11  * Permission is hereby granted, free of charge, to any person obtaining a
12  * copy of this software and associated documentation files (the "Software"),
13  * to deal in the Software without restriction, including without limitation
14  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15  * and/or sell copies of the Software, and to permit persons to whom the
16  * Software is furnished to do so, subject to the following conditions:
17  *
18  * The above copyright notice and this permission notice shall be included
19  * in all copies or substantial portions of the Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27  * DEALINGS IN THE SOFTWARE.
28  ******************************************************************************
29  *
30  * $Log$
31  * Revision 1.18  2006/03/28 14:49:16  fwarmerdam
32  * reopen overview file in update mode if needed when building overviews
33  *
34  * Revision 1.17  2005/11/17 22:02:32  fwarmerdam
35  * avoid overwriting existing .aux file, overview filename now CPLString
36  *
37  * Revision 1.16  2005/10/14 21:11:28  fwarmerdam
38  * avoid all-bands test for imagine files
39  *
40  * Revision 1.15  2005/10/12 18:21:57  fwarmerdam
41  * use GDALClose instead of delete in case dataset opened shared
42  *
43  * Revision 1.14  2005/09/26 15:52:03  fwarmerdam
44  * centralized .aux opening logic
45  *
46  * Revision 1.13  2005/09/17 03:46:18  fwarmerdam
47  * added USE_RRD support to create overviews
48  *
49  * Revision 1.12  2005/09/16 20:32:44  fwarmerdam
50  * added preliminary .aux support (read only)
51  *
52  * Revision 1.11  2005/05/10 04:48:42  fwarmerdam
53  * GDALOvLevelAdjust now public
54  *
55  * Revision 1.10  2004/07/26 22:32:30  warmerda
56  * Support .OVR files as well as .ovr
57  *
58  * Revision 1.9  2002/07/09 20:33:12  warmerda
59  * expand tabs
60  *
61  * Revision 1.8  2001/10/18 14:35:22  warmerda
62  * avoid conflicts between parameters and member data
63  *
64  * Revision 1.7  2001/07/18 04:04:30  warmerda
65  * added CPL_CVSID
66  *
67  * Revision 1.6  2001/06/22 21:00:38  warmerda
68  * fixed several problems with regenerating existing overviews
69  *
70  * Revision 1.5  2001/06/22 13:52:03  warmerda
71  * fixed bug when refreshing overviews during build
72  *
73  * Revision 1.4  2001/06/20 16:08:54  warmerda
74  * GDALDefaultOverviews now remembers ovr filename, and allows explicit setting
75  *
76  * Revision 1.3  2000/06/19 18:48:49  warmerda
77  * fixed message
78  *
79  * Revision 1.2  2000/06/19 14:42:27  warmerda
80  * Don't close old overviews till after we have identified which already
81  * exist, otherwise multiple copies of overviews may be created.
82  *
83  * Revision 1.1  2000/04/21 21:54:05  warmerda
84  * New
85  *
86  */
87
88 #include "gdal_priv.h"
89 #include "cpl_string.h"
90
91 CPL_CVSID("$Id$");
92
93 /************************************************************************/
94 /*                        GDALDefaultOverviews()                        */
95 /************************************************************************/
96
97 GDALDefaultOverviews::GDALDefaultOverviews()
98
99 {
100     poDS = NULL;
101     poODS = NULL;
102     bOvrIsAux = FALSE;
103 }
104
105 /************************************************************************/
106 /*                       ~GDALDefaultOverviews()                        */
107 /************************************************************************/
108
109 GDALDefaultOverviews::~GDALDefaultOverviews()
110
111 {
112     if( poODS != NULL )
113     {
114         poODS->FlushCache();
115         GDALClose( poODS );
116         poODS = NULL;
117     }
118 }
119
120 /************************************************************************/
121 /*                             Initialize()                             */
122 /************************************************************************/
123
124 void GDALDefaultOverviews::Initialize( GDALDataset *poDSIn,
125                                        const char * pszBasename,
126                                        int bNameIsOVR )
127
128 {
129     VSIStatBufL sStatBuf;
130
131 /* -------------------------------------------------------------------- */
132 /*      If we were already initialized, destroy the old overview        */
133 /*      file handle.                                                    */
134 /* -------------------------------------------------------------------- */
135     if( poODS != NULL )
136     {
137         GDALClose( poODS );
138         poODS = NULL;
139     }
140
141 /* -------------------------------------------------------------------- */
142 /*      Open overview dataset if it exists.                             */
143 /* -------------------------------------------------------------------- */
144     int bExists;
145
146     poDS = poDSIn;
147    
148     if( pszBasename == NULL )
149         pszBasename = poDS->GetDescription();
150
151     if( bNameIsOVR )
152         osOvrFilename = pszBasename;
153     else
154         osOvrFilename.Printf( "%s.ovr", pszBasename );
155
156     bExists = VSIStatL( osOvrFilename, &sStatBuf ) == 0;
157
158 #if !defined(WIN32)
159     if( !bNameIsOVR && !bExists )
160     {
161         osOvrFilename.Printf( "%s.OVR", pszBasename );
162         bExists = VSIStatL( osOvrFilename, &sStatBuf ) == 0;
163         if( !bExists )
164             osOvrFilename.Printf( "%s.ovr", pszBasename );
165     }
166 #endif
167
168     if( bExists )
169     {
170         poODS = (GDALDataset *) GDALOpen( osOvrFilename, poDS->GetAccess() );
171     }
172
173 /* -------------------------------------------------------------------- */
174 /*      We didn't find that, so try and find a corresponding aux        */
175 /*      file.  Check that we are the dependent file of the aux          */
176 /*      file.                                                           */
177 /* -------------------------------------------------------------------- */
178     if( !poODS )
179     {
180         poODS = GDALFindAssociatedAuxFile( pszBasename, poDS->GetAccess() );
181
182         if( poODS )
183         {
184             bOvrIsAux = TRUE;
185             osOvrFilename = poODS->GetDescription();
186         }
187     }
188 }
189
190 /************************************************************************/
191 /*                          GetOverviewCount()                          */
192 /************************************************************************/
193
194 int GDALDefaultOverviews::GetOverviewCount( int nBand )
195
196 {
197     GDALRasterBand * poBand;
198
199     if( poODS == NULL || nBand < 1 || nBand > poODS->GetRasterCount() )
200         return 0;
201
202     poBand = poODS->GetRasterBand( nBand );
203     if( poBand == NULL )
204         return 0;
205     else
206     {
207         if( bOvrIsAux )
208             return poBand->GetOverviewCount();
209         else
210             return poBand->GetOverviewCount() + 1;
211     }
212 }
213
214 /************************************************************************/
215 /*                            GetOverview()                             */
216 /************************************************************************/
217
218 GDALRasterBand *
219 GDALDefaultOverviews::GetOverview( int nBand, int iOverview )
220
221 {
222     GDALRasterBand * poBand;
223
224     if( poODS == NULL || nBand < 1 || nBand > poODS->GetRasterCount() )
225         return NULL;
226
227     poBand = poODS->GetRasterBand( nBand );
228     if( poBand == NULL )
229         return NULL;
230
231     if( bOvrIsAux )
232         return poBand->GetOverview( iOverview );
233
234     else // TIFF case, base is overview 0.
235     {
236         if( iOverview == 0 )
237             return poBand;
238         else if( iOverview-1 >= poBand->GetOverviewCount() )
239             return NULL;
240         else
241             return poBand->GetOverview( iOverview-1 );
242     }
243 }
244
245 /************************************************************************/
246 /*                         GDALOvLevelAdjust()                          */
247 /*                                                                      */
248 /*      Some overview levels cannot be achieved closely enough to be    */
249 /*      recognised as the desired overview level.  This function        */
250 /*      will adjust an overview level to one that is achievable on      */
251 /*      the given raster size.                                          */
252 /*                                                                      */
253 /*      For instance a 1200x1200 image on which a 256 level overview    */
254 /*      is request will end up generating a 5x5 overview.  However,     */
255 /*      this will appear to the system be a level 240 overview.         */
256 /*      This function will adjust 256 to 240 based on knowledge of      */
257 /*      the image size.                                                 */
258 /************************************************************************/
259
260 int GDALOvLevelAdjust( int nOvLevel, int nXSize )
261
262 {
263     int nOXSize = (nXSize + nOvLevel - 1) / nOvLevel;
264    
265     return (int) (0.5 + nXSize / (double) nOXSize);
266 }
267    
268 /************************************************************************/
269 /*                     GDALDefaultBuildOverviews()                      */
270 /************************************************************************/
271
272 CPLErr
273 GDALDefaultOverviews::BuildOverviews(
274     const char * pszBasename,
275     const char * pszResampling,
276     int nOverviews, int * panOverviewList,
277     int nBands, int * panBandList,
278     GDALProgressFunc pfnProgress, void * pProgressData)
279
280 {
281     GDALRasterBand **pahBands;
282     CPLErr       eErr;
283     int          i;
284
285 /* -------------------------------------------------------------------- */
286 /*      If we don't already have an overview file, we need to decide    */
287 /*      what format to use.                                             */
288 /* -------------------------------------------------------------------- */
289     if( poODS == NULL )
290     {
291         bOvrIsAux = CSLTestBoolean(CPLGetConfigOption( "USE_RRD", "NO" ));
292         if( bOvrIsAux )
293         {
294             VSIStatBufL sStatBuf;
295
296             osOvrFilename = CPLResetExtension(poDS->GetDescription(),"aux");
297
298             if( VSIStatL( osOvrFilename, &sStatBuf ) == 0 )
299                 osOvrFilename.Printf( "%s.aux", poDS->GetDescription() );
300         }
301     }
302 /* -------------------------------------------------------------------- */
303 /*      If we already have the overviews open, but they are             */
304 /*      read-only, then try and reopen them read-write.                 */
305 /* -------------------------------------------------------------------- */
306     else if( poODS->GetAccess() == GA_ReadOnly )
307     {
308         GDALClose( poODS );
309         poODS = (GDALDataset *) GDALOpen( osOvrFilename, GA_Update );
310         if( poODS == NULL )
311             return CE_Failure;
312     }
313
314 /* -------------------------------------------------------------------- */
315 /*      Our TIFF overview support currently only works safely if all    */
316 /*      bands are handled at the same time.                             */
317 /* -------------------------------------------------------------------- */
318     if( !bOvrIsAux && nBands != poDS->GetRasterCount() )
319     {
320         CPLError( CE_Failure, CPLE_NotSupported,
321                   "Generation of overviews in external TIFF currently only"
322                   " supported when operating on all bands.\n"
323                   "Operation failed.\n" );
324         return CE_Failure;
325     }
326
327 /* -------------------------------------------------------------------- */
328 /*      If a basename is provided, use it to override the internal      */
329 /*      overview filename.                                              */
330 /* -------------------------------------------------------------------- */
331     if( pszBasename == NULL && osOvrFilename.length() == 0  )
332         pszBasename = poDS->GetDescription();
333
334     if( pszBasename != NULL )
335     {
336         if( bOvrIsAux )
337             osOvrFilename.Printf( "%s.aux", pszBasename );
338         else
339             osOvrFilename.Printf( "%s.ovr", pszBasename );
340     }
341
342 /* -------------------------------------------------------------------- */
343 /*      Establish which of the overview levels we already have, and     */
344 /*      which are new.  We assume that band 1 of the file is            */
345 /*      representative.                                                 */
346 /* -------------------------------------------------------------------- */
347     int   nNewOverviews, *panNewOverviewList = NULL;
348     GDALRasterBand *poBand = poDS->GetRasterBand( 1 );
349
350     nNewOverviews = 0;
351     panNewOverviewList = (int *) CPLCalloc(sizeof(int),nOverviews);
352     for( i = 0; i < nOverviews && poBand != NULL; i++ )
353     {
354         int   j;
355
356         for( j = 0; j < poBand->GetOverviewCount(); j++ )
357         {
358             int    nOvFactor;
359             GDALRasterBand * poOverview = poBand->GetOverview( j );
360  
361             nOvFactor = (int)
362                 (0.5 + poBand->GetXSize() / (double) poOverview->GetXSize());
363
364             if( nOvFactor == panOverviewList[i]
365                 || nOvFactor == GDALOvLevelAdjust( panOverviewList[i],
366                                                    poBand->GetXSize() ) )
367                 panOverviewList[i] *= -1;
368         }
369
370         if( panOverviewList[i] > 0 )
371             panNewOverviewList[nNewOverviews++] = panOverviewList[i];
372     }
373
374 /* -------------------------------------------------------------------- */
375 /*      Build band list.                                                */
376 /* -------------------------------------------------------------------- */
377     pahBands = (GDALRasterBand **) CPLCalloc(sizeof(GDALRasterBand *),nBands);
378     for( i = 0; i < nBands; i++ )
379         pahBands[i] = poDS->GetRasterBand( panBandList[i] );
380
381 /* -------------------------------------------------------------------- */
382 /*      Build new overviews - Imagine.  Keep existing file open if      */
383 /*      we have it.  But mark all overviews as in need of               */
384 /*      regeneration, since HFAAuxBuildOverviews() doesn't actually     */
385 /*      produce the imagery.                                            */
386 /* -------------------------------------------------------------------- */
387     if( bOvrIsAux )
388     {
389         eErr = HFAAuxBuildOverviews( osOvrFilename, poDS, &poODS,
390                                      nBands, panBandList,
391                                      nNewOverviews, panNewOverviewList,
392                                      pszResampling,
393                                      pfnProgress, pProgressData );
394
395         int j;
396        
397         for( j = 0; j < nOverviews; j++ )
398         {
399             if( panOverviewList[j] > 0 )
400                 panOverviewList[j] *= -1;
401         }
402     }
403
404 /* -------------------------------------------------------------------- */
405 /*      Build new overviews - TIFF.  Close TIFF files while we          */
406 /*      operate on it.                                                  */
407 /* -------------------------------------------------------------------- */
408     else
409     {
410         if( poODS != NULL )
411         {
412             delete poODS;
413             poODS = NULL;
414         }
415
416         eErr = GTIFFBuildOverviews( osOvrFilename, nBands, pahBands,
417                                     nNewOverviews, panNewOverviewList,
418                                     pszResampling, pfnProgress, pProgressData );
419
420         if( eErr == CE_None )
421         {
422             poODS = (GDALDataset *) GDALOpen( osOvrFilename, GA_Update );
423             if( poODS == NULL )
424                 eErr = CE_Failure;
425         }
426     }
427
428 /* -------------------------------------------------------------------- */
429 /*      Refresh old overviews that were listed.                         */
430 /* -------------------------------------------------------------------- */
431     GDALRasterBand **papoOverviewBands;
432
433     papoOverviewBands = (GDALRasterBand **)
434         CPLCalloc(sizeof(void*),nOverviews);
435
436     for( int iBand = 0; iBand < nBands && eErr == CE_None; iBand++ )
437     {
438         poBand = poDS->GetRasterBand( panBandList[iBand] );
439
440         nNewOverviews = 0;
441         for( i = 0; i < nOverviews && poBand != NULL; i++ )
442         {
443             int   j;
444            
445             for( j = 0; j < poBand->GetOverviewCount(); j++ )
446             {
447                 int    nOvFactor;
448                 GDALRasterBand * poOverview = poBand->GetOverview( j );
449
450                 nOvFactor = (int)
451                     (0.5 + poBand->GetXSize() / (double) poOverview->GetXSize());
452
453                 if( nOvFactor == - panOverviewList[i]
454                     || nOvFactor == GDALOvLevelAdjust( -panOverviewList[i],
455                                                        poBand->GetXSize() ) )
456                 {
457                     //panOverviewList[i] *= -1;
458                     papoOverviewBands[nNewOverviews++] = poOverview;
459                 }
460             }
461         }
462
463         if( nNewOverviews > 0 )
464         {
465             eErr = GDALRegenerateOverviews( poBand,
466                                             nNewOverviews, papoOverviewBands,
467                                             pszResampling,
468                                             pfnProgress, pProgressData );
469         }
470     }
471
472 /* -------------------------------------------------------------------- */
473 /*      Cleanup                                                         */
474 /* -------------------------------------------------------------------- */
475     CPLFree( papoOverviewBands );
476     CPLFree( panNewOverviewList );
477     CPLFree( pahBands );
478
479     return eErr;
480 }
481
Note: See TracBrowser for help on using the browser.