EVOLUTION-MANAGER
Edit File: gdaladdo.cpp
/****************************************************************************** * * Project: GDAL Utilities * Purpose: Command line application to build overviews. * Author: Frank Warmerdam, warmerdam@pobox.com * ****************************************************************************** * Copyright (c) 2000, Frank Warmerdam * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "cpl_string.h" #include "gdal_version.h" #include "gdal_priv.h" #include "commonutils.h" CPL_CVSID("$Id: gdaladdo.cpp 9bae05435e199592be48a2a6c8ef5f649fa5d113 2018-03-26 14:16:35 +0200 Even Rouault $") /************************************************************************/ /* Usage() */ /************************************************************************/ static void Usage( const char* pszErrorMsg = nullptr ) { printf("Usage: gdaladdo [-r {nearest,average,gauss,cubic,cubicspline,lanczos,average_mp,average_magphase,mode}]\n" " [-ro] [-clean] [-q] [-oo NAME=VALUE]* [-minsize val]\n" " [--help-general] filename [levels]\n" "\n" " -r : choice of resampling method (default: nearest)\n" " -ro : open the dataset in read-only mode, in order to generate\n" " external overview (for GeoTIFF datasets especially)\n" " -clean : remove all overviews\n" " -q : turn off progress display\n" " -b : band to create overview (if not set overviews will be created for all bands)\n" " filename: The file to build overviews for (or whose overviews must be removed).\n" " levels: A list of integral overview levels to build. Ignored with -clean option.\n" "\n" "Useful configuration variables :\n" " --config USE_RRD YES : Use Erdas Imagine format (.aux) as overview format.\n" "Below, only for external overviews in GeoTIFF format:\n" " --config COMPRESS_OVERVIEW {JPEG,LZW,PACKBITS,DEFLATE} : TIFF compression\n" " --config PHOTOMETRIC_OVERVIEW {RGB,YCBCR,...} : TIFF photometric interp.\n" " --config INTERLEAVE_OVERVIEW {PIXEL|BAND} : TIFF interleaving method\n" " --config BIGTIFF_OVERVIEW {IF_NEEDED|IF_SAFER|YES|NO} : is BigTIFF used\n" "\n" "Examples:\n" " %% gdaladdo -r average abc.tif\n" " %% gdaladdo --config COMPRESS_OVERVIEW JPEG\n" " --config PHOTOMETRIC_OVERVIEW YCBCR\n" " --config INTERLEAVE_OVERVIEW PIXEL -ro abc.tif\n"); if( pszErrorMsg != nullptr ) fprintf(stderr, "\nFAILURE: %s\n", pszErrorMsg); exit(1); } /************************************************************************/ /* GDALAddoErrorHandler() */ /************************************************************************/ class GDALError { public: CPLErr m_eErr; CPLErrorNum m_errNum; CPLString m_osMsg; GDALError( CPLErr eErr = CE_None, CPLErrorNum errNum= CPLE_None, const char * pszMsg = "" ) : m_eErr(eErr), m_errNum(errNum), m_osMsg(pszMsg ? pszMsg : "") { } }; std::vector<GDALError> aoErrors; static void CPL_STDCALL GDALAddoErrorHandler( CPLErr eErr, CPLErrorNum errNum, const char * pszMsg ) { aoErrors.push_back(GDALError(eErr, errNum, pszMsg)); } /************************************************************************/ /* main() */ /************************************************************************/ #define CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(nExtraArg) \ do { if (iArg + nExtraArg >= nArgc) \ Usage(CPLSPrintf("%s option requires %d argument(s)", \ papszArgv[iArg], nExtraArg)); } while(false) MAIN_START(nArgc, papszArgv) { // Check that we are running against at least GDAL 1.7. // Note to developers: if we use newer API, please change the requirement. if (atoi(GDALVersionInfo("VERSION_NUM")) < 1700) { fprintf(stderr, "At least, GDAL >= 1.7.0 is required for this version of %s, " "which was compiled against GDAL %s\n", papszArgv[0], GDAL_RELEASE_NAME); exit(1); } GDALAllRegister(); nArgc = GDALGeneralCmdLineProcessor(nArgc, &papszArgv, 0); if( nArgc < 1 ) exit(-nArgc); const char *pszResampling = "nearest"; const char *pszFilename = nullptr; int anLevels[1024] = {}; int nLevelCount = 0; int nResultStatus = 0; bool bReadOnly = false; bool bClean = false; GDALProgressFunc pfnProgress = GDALTermProgress; int *panBandList = nullptr; int nBandCount = 0; char **papszOpenOptions = nullptr; int nMinSize = 256; /* -------------------------------------------------------------------- */ /* Parse command line. */ /* -------------------------------------------------------------------- */ for( int iArg = 1; iArg < nArgc; iArg++ ) { if( EQUAL(papszArgv[iArg], "--utility_version") ) { printf("%s was compiled against GDAL %s and " "is running against GDAL %s\n", papszArgv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME")); CSLDestroy(papszArgv); return 0; } else if( EQUAL(papszArgv[iArg], "--help") ) { Usage(); } else if( EQUAL(papszArgv[iArg], "-r") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); pszResampling = papszArgv[++iArg]; } else if( EQUAL(papszArgv[iArg], "-ro")) { bReadOnly = true; } else if( EQUAL(papszArgv[iArg], "-clean")) { bClean = true; } else if( EQUAL(papszArgv[iArg], "-q") || EQUAL(papszArgv[iArg], "-quiet") ) { pfnProgress = GDALDummyProgress; } else if( EQUAL(papszArgv[iArg], "-b")) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); const char* pszBand = papszArgv[iArg+1]; const int nBand = atoi(pszBand); if( nBand < 1 ) { printf("Unrecognizable band number (%s).\n", papszArgv[iArg+1]); Usage(); } iArg++; nBandCount++; panBandList = static_cast<int *>( CPLRealloc(panBandList, sizeof(int) * nBandCount)); panBandList[nBandCount-1] = nBand; } else if( EQUAL(papszArgv[iArg], "-oo") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); papszOpenOptions = CSLAddString(papszOpenOptions, papszArgv[++iArg]); } else if( EQUAL(papszArgv[iArg], "-minsize") ) { CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1); nMinSize = atoi(papszArgv[++iArg]); } else if( papszArgv[iArg][0] == '-' ) { Usage(CPLSPrintf("Unknown option name '%s'", papszArgv[iArg])); } else if( pszFilename == nullptr ) { pszFilename = papszArgv[iArg]; } else if( atoi(papszArgv[iArg]) > 0 && static_cast<size_t>(nLevelCount) < CPL_ARRAYSIZE(anLevels) ) { anLevels[nLevelCount++] = atoi(papszArgv[iArg]); if( anLevels[nLevelCount-1] == 1 ) { printf( "Warning: Overview with subsampling factor of 1 requested. " "This will copy the full resolution dataset in the " "overview!\n"); } } else { Usage("Too many command options."); } } if( pszFilename == nullptr ) Usage("No datasource specified."); /* -------------------------------------------------------------------- */ /* Open data file. */ /* -------------------------------------------------------------------- */ GDALDatasetH hDataset = nullptr; if( !bReadOnly ) { CPLPushErrorHandler(GDALAddoErrorHandler); CPLSetCurrentErrorHandlerCatchDebug(FALSE); hDataset = GDALOpenEx(pszFilename, GDAL_OF_RASTER | GDAL_OF_UPDATE, nullptr, papszOpenOptions, nullptr); CPLPopErrorHandler(); if( hDataset != nullptr ) { for(size_t i=0;i<aoErrors.size();i++) { CPLError(aoErrors[i].m_eErr, aoErrors[i].m_errNum, "%s", aoErrors[i].m_osMsg.c_str()); } } } if( hDataset == nullptr ) hDataset = GDALOpenEx(pszFilename, GDAL_OF_RASTER | GDAL_OF_VERBOSE_ERROR, nullptr, papszOpenOptions, nullptr); CSLDestroy(papszOpenOptions); papszOpenOptions = nullptr; if( hDataset == nullptr ) exit(2); /* -------------------------------------------------------------------- */ /* Clean overviews. */ /* -------------------------------------------------------------------- */ if ( bClean ) { if( GDALBuildOverviews(hDataset,pszResampling, 0, nullptr, 0, nullptr, pfnProgress, nullptr) != CE_None ) { printf("Cleaning overviews failed.\n"); nResultStatus = 200; } } else { /* -------------------------------------------------------------------- */ /* Generate overviews. */ /* -------------------------------------------------------------------- */ if( nLevelCount == 0 ) { const int nXSize = GDALGetRasterXSize(hDataset); const int nYSize = GDALGetRasterYSize(hDataset); int nOvrFactor = 1; while( DIV_ROUND_UP(nXSize, nOvrFactor) > nMinSize || DIV_ROUND_UP(nYSize, nOvrFactor) > nMinSize ) { nOvrFactor *= 2; anLevels[nLevelCount++] = nOvrFactor; } } // Only HFA supports selected layers if( nBandCount > 0 ) CPLSetConfigOption("USE_RRD", "YES"); if( nLevelCount > 0 && GDALBuildOverviews(hDataset,pszResampling, nLevelCount, anLevels, nBandCount, panBandList, pfnProgress, nullptr) != CE_None) { printf("Overview building failed.\n"); nResultStatus = 100; } } /* -------------------------------------------------------------------- */ /* Cleanup */ /* -------------------------------------------------------------------- */ GDALClose(hDataset); CSLDestroy(papszArgv); CPLFree(panBandList); GDALDestroyDriverManager(); return nResultStatus; } MAIN_END