📄 qgsrasterlayer.cpp
字号:
/* ************************************************************************** qgsrasterlayer.cpp - description -------------------begin : Sat Jun 22 2002copyright : (C) 2003 by Tim Sutton, Steve Halasz and Gary E.Shermanemail : tim at linfiniti.com ***************************************************************************//* ************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************//* $Id: qgsrasterlayer.cpp 8222 2008-03-14 14:09:18Z mhugent $ */#include "qgsapplication.h"#include "qgslogger.h"#include "qgsmaplayerregistry.h"#include "qgsmaptopixel.h"#include "qgsproviderregistry.h"#include "qgsrasterbandstats.h"#include "qgsrasterlayer.h"#include "qgsrasterpyramid.h"#include "qgsrasterviewport.h"#include "qgsrect.h"#include "qgsspatialrefsys.h"#include "gdalwarper.h"#include "cpl_conv.h"#include "qgspseudocolorshader.h"#include "qgsfreakoutshader.h"#include "qgscolorrampshader.h"#include <cstdio>#include <cmath>#include <limits>#include <iostream>#include <QApplication>#include <QCursor>#include <QDomElement>#include <QDomNode>#include <QFile>#include <QFileInfo>#include <QFont>#include <QFontMetrics>#include <QFrame>#include <QImage>#include <QLabel>#include <QList>#include <QMatrix>#include <QMessageBox>#include <QLibrary>#include <QPainter>#include <QPixmap>#include <QRegExp>#include <QSlider>// workaround for MSVC compiler which already has defined macro max// that interferes with calling std::numeric_limits<int>::max#ifdef _MSC_VER# ifdef max# undef max# endif#endif////////////////////////////////////////////////////////////// Static Methods and members first....////////////////////////////////////////////////////////////** Static member variable storing the subset of GDAL formats that we currently support. @note Some day this won't be necessary as there'll be a time when theoretically we'll support everything that GDAL can throw at us. These are GDAL driver description strings. */static const char *const mSupportedRasterFormats[] ={ "AAIGrid", "AIG", "DTED", "ECW", "GRASS", "GTiff", "HFA", "JP2ECW", "JP2KAK", "JP2MrSID", "JPEG2000", "MrSID", "SDTS", "USGSDEM", "" // used to indicate end of list};// Constant that signals property not used.const QString QgsRasterLayer::QSTRING_NOT_SET = QString("Not Set");/** Builds the list of file filter strings to later be used by QgisApp::addRasterLayer() We query GDAL for a list of supported raster formats; we then build a list of file filter strings from that list. We return a string that contains this list that is suitable for use in a a QFileDialog::getOpenFileNames() call.*/void QgsRasterLayer::buildSupportedRasterFileFilter(QString & theFileFiltersString){ // first get the GDAL driver manager registerGdalDrivers(); // then iterate through all of the supported drivers, adding the // corresponding file filter GDALDriverH myGdalDriver; // current driver char **myGdalDriverMetadata; // driver metadata strings QString myGdalDriverLongName(""); // long name for the given driver QString myGdalDriverExtension(""); // file name extension for given driver QString myGdalDriverDescription; // QString wrapper of GDAL driver description QStringList metadataTokens; // essentially the metadata string delimited by '=' QStringList catchallFilter; // for Any file(*.*), but also for those // drivers with no specific file filter GDALDriverH jp2Driver = NULL; // first JPEG2000 driver found // Grind through all the drivers and their respective metadata. // We'll add a file filter for those drivers that have a file // extension defined for them; the others, welll, even though // theoreticaly we can open those files because there exists a // driver for them, the user will have to use the "All Files" to // open datasets with no explicitly defined file name extension. // Note that file name extension strings are of the form // "DMD_EXTENSION=.*". We'll also store the long name of the // driver, which will be found in DMD_LONGNAME, which will have the // same form. for (int i = 0; i < GDALGetDriverCount(); ++i) { myGdalDriver = GDALGetDriver(i); Q_CHECK_PTR(myGdalDriver); if (!myGdalDriver) { QgsLogger::warning("unable to get driver " + QString::number(i)); continue; } // now we need to see if the driver is for something currently // supported; if not, we give it a miss for the next driver myGdalDriverDescription = GDALGetDescription(myGdalDriver); if (!isSupportedRasterDriver(myGdalDriverDescription)) { // not supported, therefore skip QgsDebugMsg("skipping unsupported driver " + QString(GDALGetDescription(myGdalDriver))); continue; } // std::cerr << "got driver string " << myGdalDriver->GetDescription() << "\n"; myGdalDriverMetadata = GDALGetMetadata(myGdalDriver,NULL); // presumably we know we've run out of metadta if either the // address is 0, or the first character is null while (myGdalDriverMetadata && '\0' != myGdalDriverMetadata[0]) { metadataTokens = QStringList::split("=", *myGdalDriverMetadata); // std::cerr << "\t" << *myGdalDriverMetadata << "\n"; // XXX add check for malformed metadataTokens // Note that it's oddly possible for there to be a // DMD_EXTENSION with no corresponding defined extension // string; so we check that there're more than two tokens. if (metadataTokens.count() > 1) { if ("DMD_EXTENSION" == metadataTokens[0]) { myGdalDriverExtension = metadataTokens[1]; } else if ("DMD_LONGNAME" == metadataTokens[0]) { myGdalDriverLongName = metadataTokens[1]; // remove any superfluous (.*) strings at the end as // they'll confuse QFileDialog::getOpenFileNames() myGdalDriverLongName.remove(QRegExp("\\(.*\\)$")); } } // if we have both the file name extension and the long name, // then we've all the information we need for the current // driver; therefore emit a file filter string and move to // the next driver if (!(myGdalDriverExtension.isEmpty() || myGdalDriverLongName.isEmpty())) { // XXX add check for SDTS; in that case we want (*CATD.DDF) QString glob = "*." + myGdalDriverExtension; // Add only the first JP2 driver found to the filter list (it's the one GDAL uses) if (myGdalDriverDescription == "JPEG2000" || myGdalDriverDescription.startsWith("JP2")) // JP2ECW, JP2KAK, JP2MrSID { if (!jp2Driver) { jp2Driver = myGdalDriver; // first JP2 driver found glob += " *.j2k"; // add alternate extension } else break; // skip if already found a JP2 driver } theFileFiltersString += myGdalDriverLongName + " (" + glob.lower() + " " + glob.upper() + ");;"; break; // ... to next driver, if any. } ++myGdalDriverMetadata; } // each metadata item if (myGdalDriverExtension.isEmpty() && !myGdalDriverLongName.isEmpty()) { // Then what we have here is a driver with no corresponding // file extension; e.g., GRASS. In which case we append the // string to the "catch-all" which will match all file types. // (I.e., "*.*") We use the driver description intead of the // long time to prevent the catch-all line from getting too // large. // ... OTOH, there are some drivers with missing // DMD_EXTENSION; so let's check for them here and handle // them appropriately // USGS DEMs use "*.dem" if (myGdalDriverDescription.startsWith("USGSDEM")) { QString glob = "*.dem"; theFileFiltersString += myGdalDriverLongName + " (" + glob.lower() + " " + glob.upper() + ");;"; } else if (myGdalDriverDescription.startsWith("DTED")) { // DTED use "*.dt0" QString glob = "*.dt0"; theFileFiltersString += myGdalDriverLongName + " (" + glob.lower() + " " + glob.upper() + ");;"; } else if (myGdalDriverDescription.startsWith("MrSID")) { // MrSID use "*.sid" QString glob = "*.sid"; theFileFiltersString += myGdalDriverLongName + " (" + glob.lower() + " " + glob.upper() + ");;"; } else { catchallFilter << QString(GDALGetDescription(myGdalDriver)); } } myGdalDriverExtension = myGdalDriverLongName = ""; // reset for next driver } // each loaded GDAL driver // can't forget the default case theFileFiltersString += catchallFilter.join(", ") + " " + tr("and all other files") + " (*)"; QgsDebugMsg("Raster filter list built: " + theFileFiltersString);} // buildSupportedRasterFileFilter_()/** ensures that GDAL drivers are registered, but only once.*/void QgsRasterLayer::registerGdalDrivers(){ if( GDALGetDriverCount() == 0 ) GDALAllRegister();}/** returns true if the given raster driver name is one currently supported, otherwise it returns false @param theDriverName GDAL driver description string */bool QgsRasterLayer::isSupportedRasterDriver(QString const &theDriverName){ size_t i = 0; while (mSupportedRasterFormats[i][0]) // while not end of string list { // If we've got a case-insensitive match for a GDAL aware driver // description, then we've got a match. Why case-insensitive? // I'm just being paranoid in that I can envision a situation // whereby GDAL slightly changes driver description string case, // in which case we'd catch it here. Not that that would likely // happen, but if it does, we'll already compensate. // GS - At Qt 3.1.2, the case sensitive argument. So we change the // driverName to lower case before testing QString format = mSupportedRasterFormats[i]; if (theDriverName.lower().startsWith(format.lower())) { return true; } i++; } return false;} // isSupportedRasterDriver/** This helper checks to see whether the filename appears to be a valid raster file name */bool QgsRasterLayer::isValidRasterFileName(QString const & theFileNameQString){ GDALDatasetH myDataset; registerGdalDrivers(); //open the file using gdal making sure we have handled locale properly myDataset = GDALOpen( QFile::encodeName(theFileNameQString).constData(), GA_ReadOnly ); if( myDataset == NULL ) { return false; } else { GDALClose(myDataset); return true; } /* * This way is no longer a good idea because it does not * cater for filetypes such as grass rasters that dont * have a predictable file extension. * QString name = theFileNameQString.lower(); return (name.endsWith(".adf") || name.endsWith(".asc") || name.endsWith(".grd") || name.endsWith(".img") || name.endsWith(".tif") || name.endsWith(".png") || name.endsWith(".jpg") || name.endsWith(".dem") || name.endsWith(".ddf")) || name.endsWith(".dt0");*/}////////////////////////////////////////////////////////////// Non Static methods now....///////////////////////////////////////////////////////////QgsRasterLayer::QgsRasterLayer( QString const & path, QString const & baseName, bool loadDefaultStyleFlag) : QgsMapLayer(RASTER, baseName, path), // XXX where is this? popMenu(0), //popMenu is the contextmenu obtained by right clicking on the legend mRasterXDim( std::numeric_limits<int>::max() ), mRasterYDim( std::numeric_limits<int>::max() ), mDebugOverlayFlag(false), mInvertPixelsFlag(false), mStandardDeviations(0), mDataProvider(0){ mUserDefinedRGBMinMaxFlag = false; //defaults needed to bypass stretch
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -