QGIS API Documentation  3.10.0-A Coruña (6c816b4204)
qgsgdalutils.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsgdalutils.cpp
3  ----------------
4  begin : September 2018
5  copyright : (C) 2018 Even Rouault
6  email : even.rouault at spatialys.com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgsgdalutils.h"
17 
18 #define CPL_SUPRESS_CPLUSPLUS //#spellok
19 #include "gdal.h"
20 #include "cpl_string.h"
21 
22 #include <QString>
23 
24 bool QgsGdalUtils::supportsRasterCreate( GDALDriverH driver )
25 {
26  QString driverShortName = GDALGetDriverShortName( driver );
27  if ( driverShortName == QLatin1String( "SQLite" ) )
28  {
29  // it supports Create() but only for vector side
30  return false;
31  }
32  char **driverMetadata = GDALGetMetadata( driver, nullptr );
33  return CSLFetchBoolean( driverMetadata, GDAL_DCAP_CREATE, false ) &&
34  CSLFetchBoolean( driverMetadata, GDAL_DCAP_RASTER, false );
35 }
36 
38 {
39  GDALDriverH hDriverMem = GDALGetDriverByName( "MEM" );
40  if ( !hDriverMem )
41  {
42  return gdal::dataset_unique_ptr();
43  }
44 
45  gdal::dataset_unique_ptr hSrcDS( GDALCreate( hDriverMem, "", width, height, 1, dataType, nullptr ) );
46 
47  double cellSizeX = extent.width() / width;
48  double cellSizeY = extent.height() / height;
49  double geoTransform[6];
50  geoTransform[0] = extent.xMinimum();
51  geoTransform[1] = cellSizeX;
52  geoTransform[2] = 0;
53  geoTransform[3] = extent.yMinimum() + ( cellSizeY * height );
54  geoTransform[4] = 0;
55  geoTransform[5] = -cellSizeY;
56 
57  GDALSetProjection( hSrcDS.get(), crs.toWkt().toLatin1().constData() );
58  GDALSetGeoTransform( hSrcDS.get(), geoTransform );
59  return hSrcDS;
60 }
61 
62 gdal::dataset_unique_ptr QgsGdalUtils::createSingleBandTiffDataset( QString filename, GDALDataType dataType, QgsRectangle extent, int width, int height, const QgsCoordinateReferenceSystem &crs )
63 {
64  double cellSizeX = extent.width() / width;
65  double cellSizeY = extent.height() / height;
66  double geoTransform[6];
67  geoTransform[0] = extent.xMinimum();
68  geoTransform[1] = cellSizeX;
69  geoTransform[2] = 0;
70  geoTransform[3] = extent.yMinimum() + ( cellSizeY * height );
71  geoTransform[4] = 0;
72  geoTransform[5] = -cellSizeY;
73 
74  GDALDriverH hDriver = GDALGetDriverByName( "GTiff" );
75  if ( !hDriver )
76  {
77  return gdal::dataset_unique_ptr();
78  }
79 
80  // Create the output file.
81  gdal::dataset_unique_ptr hDstDS( GDALCreate( hDriver, filename.toLocal8Bit().constData(), width, height, 1, dataType, nullptr ) );
82  if ( !hDstDS )
83  {
84  return gdal::dataset_unique_ptr();
85  }
86 
87  // Write out the projection definition.
88  GDALSetProjection( hDstDS.get(), crs.toWkt().toLatin1().constData() );
89  GDALSetGeoTransform( hDstDS.get(), geoTransform );
90  return hDstDS;
91 }
92 
93 void QgsGdalUtils::resampleSingleBandRaster( GDALDatasetH hSrcDS, GDALDatasetH hDstDS, GDALResampleAlg resampleAlg )
94 {
95  gdal::warp_options_unique_ptr psWarpOptions( GDALCreateWarpOptions() );
96  psWarpOptions->hSrcDS = hSrcDS;
97  psWarpOptions->hDstDS = hDstDS;
98 
99  psWarpOptions->nBandCount = 1;
100  psWarpOptions->panSrcBands = ( int * ) CPLMalloc( sizeof( int ) * 1 );
101  psWarpOptions->panDstBands = ( int * ) CPLMalloc( sizeof( int ) * 1 );
102  psWarpOptions->panSrcBands[0] = 1;
103  psWarpOptions->panDstBands[0] = 1;
104 
105  psWarpOptions->eResampleAlg = resampleAlg;
106 
107  // Establish reprojection transformer.
108  psWarpOptions->pTransformerArg =
109  GDALCreateGenImgProjTransformer( hSrcDS, GDALGetProjectionRef( hSrcDS ),
110  hDstDS, GDALGetProjectionRef( hDstDS ),
111  FALSE, 0.0, 1 );
112  psWarpOptions->pfnTransformer = GDALGenImgProjTransform;
113 
114  // Initialize and execute the warp operation.
115  GDALWarpOperation oOperation;
116  oOperation.Initialize( psWarpOptions.get() );
117 
118  oOperation.ChunkAndWarpImage( 0, 0, GDALGetRasterXSize( hDstDS ), GDALGetRasterYSize( hDstDS ) );
119 
120  GDALDestroyGenImgProjTransformer( psWarpOptions->pTransformerArg );
121 }
122 
124 {
125  QString message;
126  GDALDriverH myGdalDriver = GDALGetDriverByName( format.toLocal8Bit().constData() );
127  if ( myGdalDriver )
128  {
129  // first report details and help page
130  char **GDALmetadata = GDALGetMetadata( myGdalDriver, nullptr );
131  message += QLatin1String( "Format Details:\n" );
132  message += QStringLiteral( " Extension: %1\n" ).arg( CSLFetchNameValue( GDALmetadata, GDAL_DMD_EXTENSION ) );
133  message += QStringLiteral( " Short Name: %1" ).arg( GDALGetDriverShortName( myGdalDriver ) );
134  message += QStringLiteral( " / Long Name: %1\n" ).arg( GDALGetDriverLongName( myGdalDriver ) );
135  message += QStringLiteral( " Help page: http://www.gdal.org/%1\n\n" ).arg( CSLFetchNameValue( GDALmetadata, GDAL_DMD_HELPTOPIC ) );
136 
137  // next get creation options
138  // need to serialize xml to get newlines, should we make the basic xml prettier?
139  CPLXMLNode *psCOL = CPLParseXMLString( GDALGetMetadataItem( myGdalDriver,
140  GDAL_DMD_CREATIONOPTIONLIST, "" ) );
141  char *pszFormattedXML = CPLSerializeXMLTree( psCOL );
142  if ( pszFormattedXML )
143  message += QString( pszFormattedXML );
144  if ( psCOL )
145  CPLDestroyXMLNode( psCOL );
146  if ( pszFormattedXML )
147  CPLFree( pszFormattedXML );
148  }
149  return message;
150 }
151 
152 char **QgsGdalUtils::papszFromStringList( const QStringList &list )
153 {
154  char **papszRetList = nullptr;
155  const auto constList = list;
156  for ( const QString &elem : constList )
157  {
158  papszRetList = CSLAddString( papszRetList, elem.toLocal8Bit().constData() );
159  }
160  return papszRetList;
161 }
162 
163 QString QgsGdalUtils::validateCreationOptionsFormat( const QStringList &createOptions, QString format )
164 {
165  GDALDriverH myGdalDriver = GDALGetDriverByName( format.toLocal8Bit().constData() );
166  if ( ! myGdalDriver )
167  return QStringLiteral( "invalid GDAL driver" );
168 
169  char **papszOptions = papszFromStringList( createOptions );
170  // get error string?
171  int ok = GDALValidateCreationOptions( myGdalDriver, papszOptions );
172  CSLDestroy( papszOptions );
173 
174  if ( !ok )
175  return QStringLiteral( "Failed GDALValidateCreationOptions() test" );
176  return QString();
177 }
A rectangle specified with double values.
Definition: qgsrectangle.h:41
const QgsCoordinateReferenceSystem & crs
std::unique_ptr< GDALWarpOptions, GDALWarpOptionsDeleter > warp_options_unique_ptr
Scoped GDAL warp options.
Definition: qgsogrutils.h:149
static bool supportsRasterCreate(GDALDriverH driver)
Reads whether a driver supports GDALCreate() for raster purposes.
double width() const
Returns the width of the rectangle.
Definition: qgsrectangle.h:202
static char ** papszFromStringList(const QStringList &list)
Helper function.
static gdal::dataset_unique_ptr createSingleBandMemoryDataset(GDALDataType dataType, QgsRectangle extent, int width, int height, const QgsCoordinateReferenceSystem &crs)
Creates a new single band memory dataset with given parameters.
void * GDALDatasetH
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:177
static QString validateCreationOptionsFormat(const QStringList &createOptions, QString format)
Validates creation options for a given format, regardless of layer.
This class represents a coordinate reference system (CRS).
double xMinimum() const
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:167
static QString helpCreationOptionsFormat(QString format)
Gets creation options metadata for a given format.
static gdal::dataset_unique_ptr createSingleBandTiffDataset(QString filename, GDALDataType dataType, QgsRectangle extent, int width, int height, const QgsCoordinateReferenceSystem &crs)
Creates a new single band TIFF dataset with given parameters.
std::unique_ptr< std::remove_pointer< GDALDatasetH >::type, GDALDatasetCloser > dataset_unique_ptr
Scoped GDAL dataset.
Definition: qgsogrutils.h:134
QString toWkt(WktVariant variant=WKT1_GDAL, bool multiline=false, int indentationWidth=4) const
Returns a WKT representation of this CRS.
static void resampleSingleBandRaster(GDALDatasetH hSrcDS, GDALDatasetH hDstDS, GDALResampleAlg resampleAlg)
Resamples a single band raster to the destination dataset with different resolution (and possibly wit...
double height() const
Returns the height of the rectangle.
Definition: qgsrectangle.h:209