QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
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#include "qgslogger.h"
19#include "qgssettings.h"
21#include "qgsrasterblock.h"
22
23#define CPL_SUPRESS_CPLUSPLUS //#spellok
24#include "gdal.h"
25#include "gdalwarper.h"
26#include "cpl_string.h"
27#include "qgsapplication.h"
28
29#include <QNetworkProxy>
30#include <QString>
31#include <QImage>
32#include <QFileInfo>
33#include <mutex>
34
35bool QgsGdalUtils::supportsRasterCreate( GDALDriverH driver )
36{
37 const QString driverShortName = GDALGetDriverShortName( driver );
38 if ( driverShortName == QLatin1String( "SQLite" ) )
39 {
40 // it supports Create() but only for vector side
41 return false;
42 }
43 char **driverMetadata = GDALGetMetadata( driver, nullptr );
44 return CSLFetchBoolean( driverMetadata, GDAL_DCAP_CREATE, false ) &&
45 CSLFetchBoolean( driverMetadata, GDAL_DCAP_RASTER, false );
46}
47
49{
50 return createMultiBandMemoryDataset( dataType, 1, extent, width, height, crs );
51}
52
53gdal::dataset_unique_ptr QgsGdalUtils::createMultiBandMemoryDataset( GDALDataType dataType, int bands, const QgsRectangle &extent, int width, int height, const QgsCoordinateReferenceSystem &crs )
54{
55 GDALDriverH hDriverMem = GDALGetDriverByName( "MEM" );
56 if ( !hDriverMem )
57 {
59 }
60
61 gdal::dataset_unique_ptr hSrcDS( GDALCreate( hDriverMem, "", width, height, bands, dataType, nullptr ) );
62
63 const double cellSizeX = extent.width() / width;
64 const double cellSizeY = extent.height() / height;
65 double geoTransform[6];
66 geoTransform[0] = extent.xMinimum();
67 geoTransform[1] = cellSizeX;
68 geoTransform[2] = 0;
69 geoTransform[3] = extent.yMinimum() + ( cellSizeY * height );
70 geoTransform[4] = 0;
71 geoTransform[5] = -cellSizeY;
72
73 GDALSetProjection( hSrcDS.get(), crs.toWkt( QgsCoordinateReferenceSystem::WKT_PREFERRED_GDAL ).toLatin1().constData() );
74 GDALSetGeoTransform( hSrcDS.get(), geoTransform );
75 return hSrcDS;
76}
77
78gdal::dataset_unique_ptr QgsGdalUtils::createSingleBandTiffDataset( const QString &filename, GDALDataType dataType, const QgsRectangle &extent, int width, int height, const QgsCoordinateReferenceSystem &crs )
79{
80 const double cellSizeX = extent.width() / width;
81 const double cellSizeY = extent.height() / height;
82 double geoTransform[6];
83 geoTransform[0] = extent.xMinimum();
84 geoTransform[1] = cellSizeX;
85 geoTransform[2] = 0;
86 geoTransform[3] = extent.yMinimum() + ( cellSizeY * height );
87 geoTransform[4] = 0;
88 geoTransform[5] = -cellSizeY;
89
90 GDALDriverH hDriver = GDALGetDriverByName( "GTiff" );
91 if ( !hDriver )
92 {
94 }
95
96 // Create the output file.
97 gdal::dataset_unique_ptr hDstDS( GDALCreate( hDriver, filename.toLocal8Bit().constData(), width, height, 1, dataType, nullptr ) );
98 if ( !hDstDS )
99 {
101 }
102
103 // Write out the projection definition.
104 GDALSetProjection( hDstDS.get(), crs.toWkt( QgsCoordinateReferenceSystem::WKT_PREFERRED_GDAL ).toLatin1().constData() );
105 GDALSetGeoTransform( hDstDS.get(), geoTransform );
106 return hDstDS;
107}
108
110{
111 if ( image.isNull() )
112 return nullptr;
113
114 const QRgb *rgb = reinterpret_cast<const QRgb *>( image.constBits() );
115 GDALDriverH hDriverMem = GDALGetDriverByName( "MEM" );
116 if ( !hDriverMem )
117 {
118 return nullptr;
119 }
120 gdal::dataset_unique_ptr hSrcDS( GDALCreate( hDriverMem, "", image.width(), image.height(), 0, GDT_Byte, nullptr ) );
121
122 char **papszOptions = QgsGdalUtils::papszFromStringList( QStringList()
123 << QStringLiteral( "PIXELOFFSET=%1" ).arg( sizeof( QRgb ) )
124 << QStringLiteral( "LINEOFFSET=%1" ).arg( image.bytesPerLine() )
125 << QStringLiteral( "DATAPOINTER=%1" ).arg( reinterpret_cast< qulonglong >( rgb ) + 2 ) );
126 GDALAddBand( hSrcDS.get(), GDT_Byte, papszOptions );
127 CSLDestroy( papszOptions );
128
129 papszOptions = QgsGdalUtils::papszFromStringList( QStringList()
130 << QStringLiteral( "PIXELOFFSET=%1" ).arg( sizeof( QRgb ) )
131 << QStringLiteral( "LINEOFFSET=%1" ).arg( image.bytesPerLine() )
132 << QStringLiteral( "DATAPOINTER=%1" ).arg( reinterpret_cast< qulonglong >( rgb ) + 1 ) );
133 GDALAddBand( hSrcDS.get(), GDT_Byte, papszOptions );
134 CSLDestroy( papszOptions );
135
136 papszOptions = QgsGdalUtils::papszFromStringList( QStringList()
137 << QStringLiteral( "PIXELOFFSET=%1" ).arg( sizeof( QRgb ) )
138 << QStringLiteral( "LINEOFFSET=%1" ).arg( image.bytesPerLine() )
139 << QStringLiteral( "DATAPOINTER=%1" ).arg( reinterpret_cast< qulonglong >( rgb ) ) );
140 GDALAddBand( hSrcDS.get(), GDT_Byte, papszOptions );
141 CSLDestroy( papszOptions );
142
143 papszOptions = QgsGdalUtils::papszFromStringList( QStringList()
144 << QStringLiteral( "PIXELOFFSET=%1" ).arg( sizeof( QRgb ) )
145 << QStringLiteral( "LINEOFFSET=%1" ).arg( image.bytesPerLine() )
146 << QStringLiteral( "DATAPOINTER=%1" ).arg( reinterpret_cast< qulonglong >( rgb ) + 3 ) );
147 GDALAddBand( hSrcDS.get(), GDT_Byte, papszOptions );
148 CSLDestroy( papszOptions );
149
150 return hSrcDS;
151}
152
153gdal::dataset_unique_ptr QgsGdalUtils::blockToSingleBandMemoryDataset( int pixelWidth, int pixelHeight, const QgsRectangle &extent, void *block, GDALDataType dataType )
154{
155 if ( !block )
156 return nullptr;
157
158 GDALDriverH hDriverMem = GDALGetDriverByName( "MEM" );
159 if ( !hDriverMem )
160 return nullptr;
161
162 const double cellSizeX = extent.width() / pixelWidth;
163 const double cellSizeY = extent.height() / pixelHeight;
164 double geoTransform[6];
165 geoTransform[0] = extent.xMinimum();
166 geoTransform[1] = cellSizeX;
167 geoTransform[2] = 0;
168 geoTransform[3] = extent.yMinimum() + ( cellSizeY * pixelHeight );
169 geoTransform[4] = 0;
170 geoTransform[5] = -cellSizeY;
171
172 gdal::dataset_unique_ptr hDstDS( GDALCreate( hDriverMem, "", pixelWidth, pixelHeight, 0, dataType, nullptr ) );
173
174 int dataTypeSize = GDALGetDataTypeSizeBytes( dataType );
175 char **papszOptions = QgsGdalUtils::papszFromStringList( QStringList()
176 << QStringLiteral( "PIXELOFFSET=%1" ).arg( dataTypeSize )
177 << QStringLiteral( "LINEOFFSET=%1" ).arg( pixelWidth * dataTypeSize )
178 << QStringLiteral( "DATAPOINTER=%1" ).arg( reinterpret_cast< qulonglong >( block ) ) );
179 GDALAddBand( hDstDS.get(), dataType, papszOptions );
180 CSLDestroy( papszOptions );
181
182 GDALSetGeoTransform( hDstDS.get(), geoTransform );
183
184 return hDstDS;
185}
186
187bool QgsGdalUtils::resampleSingleBandRaster( GDALDatasetH hSrcDS, GDALDatasetH hDstDS, GDALResampleAlg resampleAlg, const char *pszCoordinateOperation )
188{
189 gdal::warp_options_unique_ptr psWarpOptions( GDALCreateWarpOptions() );
190 psWarpOptions->hSrcDS = hSrcDS;
191 psWarpOptions->hDstDS = hDstDS;
192
193 psWarpOptions->nBandCount = 1;
194 psWarpOptions->panSrcBands = reinterpret_cast< int * >( CPLMalloc( sizeof( int ) * 1 ) );
195 psWarpOptions->panDstBands = reinterpret_cast< int * >( CPLMalloc( sizeof( int ) * 1 ) );
196 psWarpOptions->panSrcBands[0] = 1;
197 psWarpOptions->panDstBands[0] = 1;
198
199 psWarpOptions->eResampleAlg = resampleAlg;
200
201 // Establish reprojection transformer.
202 char **papszOptions = nullptr;
203 if ( pszCoordinateOperation != nullptr )
204 papszOptions = CSLSetNameValue( papszOptions, "COORDINATE_OPERATION", pszCoordinateOperation );
205 psWarpOptions->pTransformerArg = GDALCreateGenImgProjTransformer2( hSrcDS, hDstDS, papszOptions );
206 CSLDestroy( papszOptions );
207
208 if ( ! psWarpOptions->pTransformerArg )
209 {
210 return false;
211 }
212
213 psWarpOptions->pfnTransformer = GDALGenImgProjTransform;
214
215 // Initialize and execute the warp operation.
216 GDALWarpOperation oOperation;
217 oOperation.Initialize( psWarpOptions.get() );
218
219 const bool retVal { oOperation.ChunkAndWarpImage( 0, 0, GDALGetRasterXSize( hDstDS ), GDALGetRasterYSize( hDstDS ) ) == CE_None };
220 GDALDestroyGenImgProjTransformer( psWarpOptions->pTransformerArg );
221 return retVal;
222}
223
224QImage QgsGdalUtils::resampleImage( const QImage &image, QSize outputSize, GDALRIOResampleAlg resampleAlg )
225{
227 if ( !srcDS )
228 return QImage();
229
230 GDALRasterIOExtraArg extra;
231 INIT_RASTERIO_EXTRA_ARG( extra );
232 extra.eResampleAlg = resampleAlg;
233
234 QImage res( outputSize, image.format() );
235 if ( res.isNull() )
236 return QImage();
237
238 GByte *rgb = reinterpret_cast<GByte *>( res.bits() );
239
240 CPLErr err = GDALRasterIOEx( GDALGetRasterBand( srcDS.get(), 1 ), GF_Read, 0, 0, image.width(), image.height(), rgb + 2, outputSize.width(),
241 outputSize.height(), GDT_Byte, sizeof( QRgb ), res.bytesPerLine(), &extra );
242 if ( err != CE_None )
243 {
244 QgsDebugMsg( QStringLiteral( "failed to read red band" ) );
245 return QImage();
246 }
247
248 err = GDALRasterIOEx( GDALGetRasterBand( srcDS.get(), 2 ), GF_Read, 0, 0, image.width(), image.height(), rgb + 1, outputSize.width(),
249 outputSize.height(), GDT_Byte, sizeof( QRgb ), res.bytesPerLine(), &extra );
250 if ( err != CE_None )
251 {
252 QgsDebugMsg( QStringLiteral( "failed to read green band" ) );
253 return QImage();
254 }
255
256 err = GDALRasterIOEx( GDALGetRasterBand( srcDS.get(), 3 ), GF_Read, 0, 0, image.width(), image.height(), rgb, outputSize.width(),
257 outputSize.height(), GDT_Byte, sizeof( QRgb ), res.bytesPerLine(), &extra );
258 if ( err != CE_None )
259 {
260 QgsDebugMsg( QStringLiteral( "failed to read blue band" ) );
261 return QImage();
262 }
263
264 err = GDALRasterIOEx( GDALGetRasterBand( srcDS.get(), 4 ), GF_Read, 0, 0, image.width(), image.height(), rgb + 3, outputSize.width(),
265 outputSize.height(), GDT_Byte, sizeof( QRgb ), res.bytesPerLine(), &extra );
266 if ( err != CE_None )
267 {
268 QgsDebugMsg( QStringLiteral( "failed to read alpha band" ) );
269 return QImage();
270 }
271
272 return res;
273}
274
275QString QgsGdalUtils::helpCreationOptionsFormat( const QString &format )
276{
277 QString message;
278 GDALDriverH myGdalDriver = GDALGetDriverByName( format.toLocal8Bit().constData() );
279 if ( myGdalDriver )
280 {
281 // first report details and help page
282 char **GDALmetadata = GDALGetMetadata( myGdalDriver, nullptr );
283 message += QLatin1String( "Format Details:\n" );
284 message += QStringLiteral( " Extension: %1\n" ).arg( CSLFetchNameValue( GDALmetadata, GDAL_DMD_EXTENSION ) );
285 message += QStringLiteral( " Short Name: %1" ).arg( GDALGetDriverShortName( myGdalDriver ) );
286 message += QStringLiteral( " / Long Name: %1\n" ).arg( GDALGetDriverLongName( myGdalDriver ) );
287 message += QStringLiteral( " Help page: http://www.gdal.org/%1\n\n" ).arg( CSLFetchNameValue( GDALmetadata, GDAL_DMD_HELPTOPIC ) );
288
289 // next get creation options
290 // need to serialize xml to get newlines, should we make the basic xml prettier?
291 CPLXMLNode *psCOL = CPLParseXMLString( GDALGetMetadataItem( myGdalDriver,
292 GDAL_DMD_CREATIONOPTIONLIST, "" ) );
293 char *pszFormattedXML = CPLSerializeXMLTree( psCOL );
294 if ( pszFormattedXML )
295 message += QString( pszFormattedXML );
296 if ( psCOL )
297 CPLDestroyXMLNode( psCOL );
298 if ( pszFormattedXML )
299 CPLFree( pszFormattedXML );
300 }
301 return message;
302}
303
304char **QgsGdalUtils::papszFromStringList( const QStringList &list )
305{
306 char **papszRetList = nullptr;
307 const auto constList = list;
308 for ( const QString &elem : constList )
309 {
310 papszRetList = CSLAddString( papszRetList, elem.toLocal8Bit().constData() );
311 }
312 return papszRetList;
313}
314
315QString QgsGdalUtils::validateCreationOptionsFormat( const QStringList &createOptions, const QString &format )
316{
317 GDALDriverH myGdalDriver = GDALGetDriverByName( format.toLocal8Bit().constData() );
318 if ( ! myGdalDriver )
319 return QStringLiteral( "invalid GDAL driver" );
320
321 char **papszOptions = papszFromStringList( createOptions );
322 // get error string?
323 const int ok = GDALValidateCreationOptions( myGdalDriver, papszOptions );
324 CSLDestroy( papszOptions );
325
326 if ( !ok )
327 return QStringLiteral( "Failed GDALValidateCreationOptions() test" );
328 return QString();
329}
330
332 GDALDatasetH hSrcDS,
333 const char *pszSrcWKT,
334 const char *pszDstWKT,
335 GDALResampleAlg eResampleAlg,
336 double dfMaxError,
337 const GDALWarpOptions *psOptionsIn )
338{
339 char **opts = nullptr;
340 if ( GDALGetMetadata( hSrcDS, "RPC" ) )
341 {
342 // well-behaved RPC should have height offset a good value for RPC_HEIGHT
343 const char *heightOffStr = GDALGetMetadataItem( hSrcDS, "HEIGHT_OFF", "RPC" );
344 if ( heightOffStr )
345 opts = CSLAddNameValue( opts, "RPC_HEIGHT", heightOffStr );
346 }
347
348 return GDALAutoCreateWarpedVRTEx( hSrcDS, pszSrcWKT, pszDstWKT, eResampleAlg, dfMaxError, psOptionsIn, opts );
349}
350
351void *QgsGdalUtils::rpcAwareCreateTransformer( GDALDatasetH hSrcDS, GDALDatasetH hDstDS, char **papszOptions )
352{
353 char **opts = CSLDuplicate( papszOptions );
354 if ( GDALGetMetadata( hSrcDS, "RPC" ) )
355 {
356 // well-behaved RPC should have height offset a good value for RPC_HEIGHT
357 const char *heightOffStr = GDALGetMetadataItem( hSrcDS, "HEIGHT_OFF", "RPC" );
358 if ( heightOffStr )
359 opts = CSLAddNameValue( opts, "RPC_HEIGHT", heightOffStr );
360 }
361 void *transformer = GDALCreateGenImgProjTransformer2( hSrcDS, hDstDS, opts );
362 CSLDestroy( opts );
363 return transformer;
364}
365
366#ifndef QT_NO_NETWORKPROXY
368{
369 // Check proxy configuration, they are application level but
370 // instead of adding an API and complex signal/slot connections
371 // given the limited cost of checking them on every provider instantiation
372 // we can do it here so that new settings are applied whenever a new layer
373 // is created.
374 const QgsSettings settings;
375 // Check that proxy is enabled
376 if ( settings.value( QStringLiteral( "proxy/proxyEnabled" ), false ).toBool() )
377 {
378 // Get the first configured proxy
379 QList<QNetworkProxy> proxies( QgsNetworkAccessManager::instance()->proxyFactory()->queryProxy( ) );
380 if ( ! proxies.isEmpty() )
381 {
382 const QNetworkProxy proxy( proxies.first() );
383 // TODO/FIXME: check excludes (the GDAL config options are global, we need a per-connection config option)
384 //QStringList excludes;
385 //excludes = settings.value( QStringLiteral( "proxy/proxyExcludedUrls" ), "" ).toStringList();
386
387 const QString proxyHost( proxy.hostName() );
388 const quint16 proxyPort( proxy.port() );
389
390 const QString proxyUser( proxy.user() );
391 const QString proxyPassword( proxy.password() );
392
393 if ( ! proxyHost.isEmpty() )
394 {
395 QString connection( proxyHost );
396 if ( proxyPort )
397 {
398 connection += ':' + QString::number( proxyPort );
399 }
400 CPLSetConfigOption( "GDAL_HTTP_PROXY", connection.toUtf8() );
401 if ( ! proxyUser.isEmpty( ) )
402 {
403 QString credentials( proxyUser );
404 if ( ! proxyPassword.isEmpty( ) )
405 {
406 credentials += ':' + proxyPassword;
407 }
408 CPLSetConfigOption( "GDAL_HTTP_PROXYUSERPWD", credentials.toUtf8() );
409 }
410 }
411 }
412 }
413}
414
415bool QgsGdalUtils::pathIsCheapToOpen( const QString &path, int smallFileSizeLimit )
416{
417 const QFileInfo info( path );
418 const long long size = info.size();
419
420 // if size could not be determined, safest to flag path as expensive
421 if ( size == 0 )
422 return false;
423
424 const QString suffix = info.suffix().toLower();
425 static const QStringList sFileSizeDependentExtensions
426 {
427 QStringLiteral( "xlsx" ),
428 QStringLiteral( "ods" ),
429 QStringLiteral( "csv" )
430 };
431 if ( sFileSizeDependentExtensions.contains( suffix ) )
432 {
433 // path corresponds to a file type which is only cheap to open for small files
434 return size < smallFileSizeLimit;
435 }
436
437 // treat all other formats as expensive.
438 // TODO -- flag formats which only require a quick header parse as cheap
439 return false;
440}
441
443{
444#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,4,0)
445 // get supported extensions
446 static std::once_flag initialized;
447 static QStringList SUPPORTED_DB_LAYERS_EXTENSIONS;
448 std::call_once( initialized, [ = ]
449 {
450 // iterate through all of the supported drivers, adding the corresponding file extensions for
451 // types which advertise multilayer support
452 GDALDriverH driver = nullptr;
453
454 QSet< QString > extensions;
455
456 for ( int i = 0; i < GDALGetDriverCount(); ++i )
457 {
458 driver = GDALGetDriver( i );
459 if ( !driver )
460 {
461 QgsLogger::warning( "unable to get driver " + QString::number( i ) );
462 continue;
463 }
464
465 bool isMultiLayer = false;
466 if ( QString( GDALGetMetadataItem( driver, GDAL_DCAP_RASTER, nullptr ) ) == QLatin1String( "YES" ) )
467 {
468 if ( GDALGetMetadataItem( driver, GDAL_DMD_SUBDATASETS, nullptr ) != nullptr )
469 {
470 isMultiLayer = true;
471 }
472 }
473 if ( !isMultiLayer && QString( GDALGetMetadataItem( driver, GDAL_DCAP_VECTOR, nullptr ) ) == QLatin1String( "YES" ) )
474 {
475 if ( GDALGetMetadataItem( driver, GDAL_DCAP_MULTIPLE_VECTOR_LAYERS, nullptr ) != nullptr )
476 {
477 isMultiLayer = true;
478 }
479 }
480
481 if ( !isMultiLayer )
482 continue;
483
484 const QString driverExtensions = GDALGetMetadataItem( driver, GDAL_DMD_EXTENSIONS, "" );
485 if ( driverExtensions.isEmpty() )
486 continue;
487
488 const QStringList splitExtensions = driverExtensions.split( ' ', Qt::SkipEmptyParts );
489
490 for ( const QString &ext : splitExtensions )
491 extensions.insert( ext );
492 }
493
494 SUPPORTED_DB_LAYERS_EXTENSIONS = QStringList( extensions.constBegin(), extensions.constEnd() );
495 } );
496 return SUPPORTED_DB_LAYERS_EXTENSIONS;
497
498#else
499 static const QStringList SUPPORTED_DB_LAYERS_EXTENSIONS
500 {
501 QStringLiteral( "gpkg" ),
502 QStringLiteral( "sqlite" ),
503 QStringLiteral( "db" ),
504 QStringLiteral( "gdb" ),
505 QStringLiteral( "kml" ),
506 QStringLiteral( "kmz" ),
507 QStringLiteral( "osm" ),
508 QStringLiteral( "mdb" ),
509 QStringLiteral( "accdb" ),
510 QStringLiteral( "xls" ),
511 QStringLiteral( "xlsx" ),
512 QStringLiteral( "ods" ),
513 QStringLiteral( "gpx" ),
514 QStringLiteral( "pdf" ),
515 QStringLiteral( "pbf" ),
516 QStringLiteral( "vrt" ),
517 QStringLiteral( "nc" ),
518 QStringLiteral( "shp.zip" ) };
519 return SUPPORTED_DB_LAYERS_EXTENSIONS;
520#endif
521}
522
523bool QgsGdalUtils::vrtMatchesLayerType( const QString &vrtPath, QgsMapLayerType type )
524{
525 CPLPushErrorHandler( CPLQuietErrorHandler );
526 CPLErrorReset();
527 GDALDriverH hDriver = nullptr;
528
529 switch ( type )
530 {
532 hDriver = GDALIdentifyDriverEx( vrtPath.toUtf8().constData(), GDAL_OF_VECTOR, nullptr, nullptr );
533 break;
534
536 hDriver = GDALIdentifyDriverEx( vrtPath.toUtf8().constData(), GDAL_OF_RASTER, nullptr, nullptr );
537 break;
538
545 break;
546 }
547
548 CPLPopErrorHandler();
549 return static_cast< bool >( hDriver );
550}
551#endif
This class represents a coordinate reference system (CRS).
@ WKT_PREFERRED_GDAL
Preferred format for conversion of CRS to WKT for use with the GDAL library.
QString toWkt(WktVariant variant=WKT1_GDAL, bool multiline=false, int indentationWidth=4) const
Returns a WKT representation of this CRS.
static bool pathIsCheapToOpen(const QString &path, int smallFileSizeLimit=50000)
Returns true if the dataset at the specified path is considered "cheap" to open.
static QString helpCreationOptionsFormat(const QString &format)
Gets creation options metadata for a given format.
static bool resampleSingleBandRaster(GDALDatasetH hSrcDS, GDALDatasetH hDstDS, GDALResampleAlg resampleAlg, const char *pszCoordinateOperation)
Resamples a single band raster to the destination dataset with different resolution (and possibly wit...
static GDALDatasetH rpcAwareAutoCreateWarpedVrt(GDALDatasetH hSrcDS, const char *pszSrcWKT, const char *pszDstWKT, GDALResampleAlg eResampleAlg, double dfMaxError, const GDALWarpOptions *psOptionsIn)
This is a copy of GDALAutoCreateWarpedVRT optimized for imagery using RPC georeferencing that also se...
static bool supportsRasterCreate(GDALDriverH driver)
Reads whether a driver supports GDALCreate() for raster purposes.
static gdal::dataset_unique_ptr createSingleBandTiffDataset(const QString &filename, GDALDataType dataType, const QgsRectangle &extent, int width, int height, const QgsCoordinateReferenceSystem &crs)
Creates a new single band TIFF dataset with given parameters.
static gdal::dataset_unique_ptr createSingleBandMemoryDataset(GDALDataType dataType, const QgsRectangle &extent, int width, int height, const QgsCoordinateReferenceSystem &crs)
Creates a new single band memory dataset with given parameters.
static QString validateCreationOptionsFormat(const QStringList &createOptions, const QString &format)
Validates creation options for a given format, regardless of layer.
static gdal::dataset_unique_ptr blockToSingleBandMemoryDataset(int pixelWidth, int pixelHeight, const QgsRectangle &extent, void *block, GDALDataType dataType)
Converts an raster block to a single band GDAL memory dataset.
static gdal::dataset_unique_ptr imageToMemoryDataset(const QImage &image)
Converts an image to a GDAL memory dataset by borrowing image data.
static void * rpcAwareCreateTransformer(GDALDatasetH hSrcDS, GDALDatasetH hDstDS=nullptr, char **papszOptions=nullptr)
This is a wrapper around GDALCreateGenImgProjTransformer2() that takes into account RPC georeferencin...
static void setupProxy()
Sets the gdal proxy variables.
static bool vrtMatchesLayerType(const QString &vrtPath, QgsMapLayerType type)
Returns true if the VRT file at the specified path is a VRT matching the given layer type.
static char ** papszFromStringList(const QStringList &list)
Helper function.
static QImage resampleImage(const QImage &image, QSize outputSize, GDALRIOResampleAlg resampleAlg)
Resamples a QImage image using GDAL resampler.
static gdal::dataset_unique_ptr createMultiBandMemoryDataset(GDALDataType dataType, int bands, const QgsRectangle &extent, int width, int height, const QgsCoordinateReferenceSystem &crs)
Creates a new multi band memory dataset with given parameters.
static QStringList multiLayerFileExtensions()
Returns a list of file extensions which potentially contain multiple layers representing GDAL raster ...
static void warning(const QString &msg)
Goes to qWarning.
Definition: qgslogger.cpp:122
static QgsNetworkAccessManager * instance(Qt::ConnectionType connectionType=Qt::BlockingQueuedConnection)
Returns a pointer to the active QgsNetworkAccessManager for the current thread.
A rectangle specified with double values.
Definition: qgsrectangle.h:42
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:188
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:198
double height() const SIP_HOLDGIL
Returns the height of the rectangle.
Definition: qgsrectangle.h:230
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
Definition: qgsrectangle.h:223
This class is a composition of two QSettings instances:
Definition: qgssettings.h:62
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
QgsMapLayerType
Types of layers that can be added to a map.
Definition: qgis.h:47
@ PointCloudLayer
Point cloud layer. Added in QGIS 3.18.
@ MeshLayer
Mesh layer. Added in QGIS 3.2.
@ VectorLayer
Vector layer.
@ RasterLayer
Raster layer.
@ GroupLayer
Composite group layer. Added in QGIS 3.24.
@ VectorTileLayer
Vector tile layer. Added in QGIS 3.14.
@ AnnotationLayer
Contains freeform, georeferenced annotations. Added in QGIS 3.16.
@ PluginLayer
Plugin based layer.
std::unique_ptr< std::remove_pointer< GDALDatasetH >::type, GDALDatasetCloser > dataset_unique_ptr
Scoped GDAL dataset.
Definition: qgsogrutils.h:140
std::unique_ptr< GDALWarpOptions, GDALWarpOptionsDeleter > warp_options_unique_ptr
Scoped GDAL warp options.
Definition: qgsogrutils.h:155
void * GDALDatasetH
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
const QgsCoordinateReferenceSystem & crs