QGIS API Documentation  3.18.1-Zürich (202f1bf7e5)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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"
20 
21 #define CPL_SUPRESS_CPLUSPLUS //#spellok
22 #include "gdal.h"
23 #include "gdalwarper.h"
24 #include "cpl_string.h"
25 
26 #include <QNetworkProxy>
27 #include <QString>
28 #include <QImage>
29 
30 bool QgsGdalUtils::supportsRasterCreate( GDALDriverH driver )
31 {
32  QString driverShortName = GDALGetDriverShortName( driver );
33  if ( driverShortName == QLatin1String( "SQLite" ) )
34  {
35  // it supports Create() but only for vector side
36  return false;
37  }
38  char **driverMetadata = GDALGetMetadata( driver, nullptr );
39  return CSLFetchBoolean( driverMetadata, GDAL_DCAP_CREATE, false ) &&
40  CSLFetchBoolean( driverMetadata, GDAL_DCAP_RASTER, false );
41 }
42 
43 gdal::dataset_unique_ptr QgsGdalUtils::createSingleBandMemoryDataset( GDALDataType dataType, const QgsRectangle &extent, int width, int height, const QgsCoordinateReferenceSystem &crs )
44 {
45  return createMultiBandMemoryDataset( dataType, 1, extent, width, height, crs );
46 }
47 
48 gdal::dataset_unique_ptr QgsGdalUtils::createMultiBandMemoryDataset( GDALDataType dataType, int bands, const QgsRectangle &extent, int width, int height, const QgsCoordinateReferenceSystem &crs )
49 {
50  GDALDriverH hDriverMem = GDALGetDriverByName( "MEM" );
51  if ( !hDriverMem )
52  {
53  return gdal::dataset_unique_ptr();
54  }
55 
56  gdal::dataset_unique_ptr hSrcDS( GDALCreate( hDriverMem, "", width, height, bands, dataType, nullptr ) );
57 
58  double cellSizeX = extent.width() / width;
59  double cellSizeY = extent.height() / height;
60  double geoTransform[6];
61  geoTransform[0] = extent.xMinimum();
62  geoTransform[1] = cellSizeX;
63  geoTransform[2] = 0;
64  geoTransform[3] = extent.yMinimum() + ( cellSizeY * height );
65  geoTransform[4] = 0;
66  geoTransform[5] = -cellSizeY;
67 
68  GDALSetProjection( hSrcDS.get(), crs.toWkt( QgsCoordinateReferenceSystem::WKT_PREFERRED_GDAL ).toLatin1().constData() );
69  GDALSetGeoTransform( hSrcDS.get(), geoTransform );
70  return hSrcDS;
71 }
72 
73 gdal::dataset_unique_ptr QgsGdalUtils::createSingleBandTiffDataset( const QString &filename, GDALDataType dataType, const QgsRectangle &extent, int width, int height, const QgsCoordinateReferenceSystem &crs )
74 {
75  double cellSizeX = extent.width() / width;
76  double cellSizeY = extent.height() / height;
77  double geoTransform[6];
78  geoTransform[0] = extent.xMinimum();
79  geoTransform[1] = cellSizeX;
80  geoTransform[2] = 0;
81  geoTransform[3] = extent.yMinimum() + ( cellSizeY * height );
82  geoTransform[4] = 0;
83  geoTransform[5] = -cellSizeY;
84 
85  GDALDriverH hDriver = GDALGetDriverByName( "GTiff" );
86  if ( !hDriver )
87  {
88  return gdal::dataset_unique_ptr();
89  }
90 
91  // Create the output file.
92  gdal::dataset_unique_ptr hDstDS( GDALCreate( hDriver, filename.toLocal8Bit().constData(), width, height, 1, dataType, nullptr ) );
93  if ( !hDstDS )
94  {
95  return gdal::dataset_unique_ptr();
96  }
97 
98  // Write out the projection definition.
99  GDALSetProjection( hDstDS.get(), crs.toWkt( QgsCoordinateReferenceSystem::WKT_PREFERRED_GDAL ).toLatin1().constData() );
100  GDALSetGeoTransform( hDstDS.get(), geoTransform );
101  return hDstDS;
102 }
103 
105 {
106  if ( image.isNull() )
107  return nullptr;
108 
109  const QRgb *rgb = reinterpret_cast<const QRgb *>( image.constBits() );
110  GDALDriverH hDriverMem = GDALGetDriverByName( "MEM" );
111  if ( !hDriverMem )
112  {
113  return nullptr;
114  }
115  gdal::dataset_unique_ptr hSrcDS( GDALCreate( hDriverMem, "", image.width(), image.height(), 0, GDT_Byte, nullptr ) );
116 
117  char **papszOptions = QgsGdalUtils::papszFromStringList( QStringList()
118  << QStringLiteral( "PIXELOFFSET=%1" ).arg( sizeof( QRgb ) )
119  << QStringLiteral( "LINEOFFSET=%1" ).arg( image.bytesPerLine() )
120  << QStringLiteral( "DATAPOINTER=%1" ).arg( reinterpret_cast< qulonglong >( rgb ) + 2 ) );
121  GDALAddBand( hSrcDS.get(), GDT_Byte, papszOptions );
122  CSLDestroy( papszOptions );
123 
124  papszOptions = QgsGdalUtils::papszFromStringList( QStringList()
125  << QStringLiteral( "PIXELOFFSET=%1" ).arg( sizeof( QRgb ) )
126  << QStringLiteral( "LINEOFFSET=%1" ).arg( image.bytesPerLine() )
127  << QStringLiteral( "DATAPOINTER=%1" ).arg( reinterpret_cast< qulonglong >( rgb ) + 1 ) );
128  GDALAddBand( hSrcDS.get(), GDT_Byte, papszOptions );
129  CSLDestroy( papszOptions );
130 
131  papszOptions = QgsGdalUtils::papszFromStringList( QStringList()
132  << QStringLiteral( "PIXELOFFSET=%1" ).arg( sizeof( QRgb ) )
133  << QStringLiteral( "LINEOFFSET=%1" ).arg( image.bytesPerLine() )
134  << QStringLiteral( "DATAPOINTER=%1" ).arg( reinterpret_cast< qulonglong >( rgb ) ) );
135  GDALAddBand( hSrcDS.get(), GDT_Byte, papszOptions );
136  CSLDestroy( papszOptions );
137 
138  papszOptions = QgsGdalUtils::papszFromStringList( QStringList()
139  << QStringLiteral( "PIXELOFFSET=%1" ).arg( sizeof( QRgb ) )
140  << QStringLiteral( "LINEOFFSET=%1" ).arg( image.bytesPerLine() )
141  << QStringLiteral( "DATAPOINTER=%1" ).arg( reinterpret_cast< qulonglong >( rgb ) + 3 ) );
142  GDALAddBand( hSrcDS.get(), GDT_Byte, papszOptions );
143  CSLDestroy( papszOptions );
144 
145  return hSrcDS;
146 }
147 
148 bool QgsGdalUtils::resampleSingleBandRaster( GDALDatasetH hSrcDS, GDALDatasetH hDstDS, GDALResampleAlg resampleAlg, const char *pszCoordinateOperation )
149 {
150  gdal::warp_options_unique_ptr psWarpOptions( GDALCreateWarpOptions() );
151  psWarpOptions->hSrcDS = hSrcDS;
152  psWarpOptions->hDstDS = hDstDS;
153 
154  psWarpOptions->nBandCount = 1;
155  psWarpOptions->panSrcBands = reinterpret_cast< int * >( CPLMalloc( sizeof( int ) * 1 ) );
156  psWarpOptions->panDstBands = reinterpret_cast< int * >( CPLMalloc( sizeof( int ) * 1 ) );
157  psWarpOptions->panSrcBands[0] = 1;
158  psWarpOptions->panDstBands[0] = 1;
159 
160  psWarpOptions->eResampleAlg = resampleAlg;
161 
162  // Establish reprojection transformer.
163  char **papszOptions = nullptr;
164  if ( pszCoordinateOperation != nullptr )
165  papszOptions = CSLSetNameValue( papszOptions, "COORDINATE_OPERATION", pszCoordinateOperation );
166  psWarpOptions->pTransformerArg = GDALCreateGenImgProjTransformer2( hSrcDS, hDstDS, papszOptions );
167  CSLDestroy( papszOptions );
168 
169  if ( ! psWarpOptions->pTransformerArg )
170  {
171  return false;
172  }
173 
174  psWarpOptions->pfnTransformer = GDALGenImgProjTransform;
175 
176  // Initialize and execute the warp operation.
177  GDALWarpOperation oOperation;
178  oOperation.Initialize( psWarpOptions.get() );
179 
180  const bool retVal { oOperation.ChunkAndWarpImage( 0, 0, GDALGetRasterXSize( hDstDS ), GDALGetRasterYSize( hDstDS ) ) == CE_None };
181  GDALDestroyGenImgProjTransformer( psWarpOptions->pTransformerArg );
182  return retVal;
183 }
184 
185 QImage QgsGdalUtils::resampleImage( const QImage &image, QSize outputSize, GDALRIOResampleAlg resampleAlg )
186 {
188  if ( !srcDS )
189  return QImage();
190 
191  GDALRasterIOExtraArg extra;
192  INIT_RASTERIO_EXTRA_ARG( extra );
193  extra.eResampleAlg = resampleAlg;
194 
195  QImage res( outputSize, image.format() );
196  if ( res.isNull() )
197  return QImage();
198 
199  GByte *rgb = reinterpret_cast<GByte *>( res.bits() );
200 
201  CPLErr err = GDALRasterIOEx( GDALGetRasterBand( srcDS.get(), 1 ), GF_Read, 0, 0, image.width(), image.height(), rgb + 2, outputSize.width(),
202  outputSize.height(), GDT_Byte, sizeof( QRgb ), res.bytesPerLine(), &extra );
203  if ( err != CE_None )
204  {
205  QgsDebugMsg( QStringLiteral( "failed to read red band" ) );
206  return QImage();
207  }
208 
209  err = GDALRasterIOEx( GDALGetRasterBand( srcDS.get(), 2 ), GF_Read, 0, 0, image.width(), image.height(), rgb + 1, outputSize.width(),
210  outputSize.height(), GDT_Byte, sizeof( QRgb ), res.bytesPerLine(), &extra );
211  if ( err != CE_None )
212  {
213  QgsDebugMsg( QStringLiteral( "failed to read green band" ) );
214  return QImage();
215  }
216 
217  err = GDALRasterIOEx( GDALGetRasterBand( srcDS.get(), 3 ), GF_Read, 0, 0, image.width(), image.height(), rgb, outputSize.width(),
218  outputSize.height(), GDT_Byte, sizeof( QRgb ), res.bytesPerLine(), &extra );
219  if ( err != CE_None )
220  {
221  QgsDebugMsg( QStringLiteral( "failed to read blue band" ) );
222  return QImage();
223  }
224 
225  err = GDALRasterIOEx( GDALGetRasterBand( srcDS.get(), 4 ), GF_Read, 0, 0, image.width(), image.height(), rgb + 3, outputSize.width(),
226  outputSize.height(), GDT_Byte, sizeof( QRgb ), res.bytesPerLine(), &extra );
227  if ( err != CE_None )
228  {
229  QgsDebugMsg( QStringLiteral( "failed to read alpha band" ) );
230  return QImage();
231  }
232 
233  return res;
234 }
235 
236 QString QgsGdalUtils::helpCreationOptionsFormat( const QString &format )
237 {
238  QString message;
239  GDALDriverH myGdalDriver = GDALGetDriverByName( format.toLocal8Bit().constData() );
240  if ( myGdalDriver )
241  {
242  // first report details and help page
243  char **GDALmetadata = GDALGetMetadata( myGdalDriver, nullptr );
244  message += QLatin1String( "Format Details:\n" );
245  message += QStringLiteral( " Extension: %1\n" ).arg( CSLFetchNameValue( GDALmetadata, GDAL_DMD_EXTENSION ) );
246  message += QStringLiteral( " Short Name: %1" ).arg( GDALGetDriverShortName( myGdalDriver ) );
247  message += QStringLiteral( " / Long Name: %1\n" ).arg( GDALGetDriverLongName( myGdalDriver ) );
248  message += QStringLiteral( " Help page: http://www.gdal.org/%1\n\n" ).arg( CSLFetchNameValue( GDALmetadata, GDAL_DMD_HELPTOPIC ) );
249 
250  // next get creation options
251  // need to serialize xml to get newlines, should we make the basic xml prettier?
252  CPLXMLNode *psCOL = CPLParseXMLString( GDALGetMetadataItem( myGdalDriver,
253  GDAL_DMD_CREATIONOPTIONLIST, "" ) );
254  char *pszFormattedXML = CPLSerializeXMLTree( psCOL );
255  if ( pszFormattedXML )
256  message += QString( pszFormattedXML );
257  if ( psCOL )
258  CPLDestroyXMLNode( psCOL );
259  if ( pszFormattedXML )
260  CPLFree( pszFormattedXML );
261  }
262  return message;
263 }
264 
265 char **QgsGdalUtils::papszFromStringList( const QStringList &list )
266 {
267  char **papszRetList = nullptr;
268  const auto constList = list;
269  for ( const QString &elem : constList )
270  {
271  papszRetList = CSLAddString( papszRetList, elem.toLocal8Bit().constData() );
272  }
273  return papszRetList;
274 }
275 
276 QString QgsGdalUtils::validateCreationOptionsFormat( const QStringList &createOptions, const QString &format )
277 {
278  GDALDriverH myGdalDriver = GDALGetDriverByName( format.toLocal8Bit().constData() );
279  if ( ! myGdalDriver )
280  return QStringLiteral( "invalid GDAL driver" );
281 
282  char **papszOptions = papszFromStringList( createOptions );
283  // get error string?
284  int ok = GDALValidateCreationOptions( myGdalDriver, papszOptions );
285  CSLDestroy( papszOptions );
286 
287  if ( !ok )
288  return QStringLiteral( "Failed GDALValidateCreationOptions() test" );
289  return QString();
290 }
291 
292 #if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(2,3,0)
293 // GDAL < 2.3 does not come with GDALWarpInitDefaultBandMapping and GDALWarpInitNoDataReal
294 // in the public API so we define them here for rpcAwareAutoCreateWarpedVrt()
295 
296 static void GDALWarpInitDefaultBandMapping( GDALWarpOptions *psOptionsIn, int nBandCount )
297 {
298  if ( psOptionsIn->nBandCount != 0 ) { return; }
299 
300  psOptionsIn->nBandCount = nBandCount;
301 
302  psOptionsIn->panSrcBands = static_cast<int *>(
303  CPLMalloc( sizeof( int ) * psOptionsIn->nBandCount ) );
304  psOptionsIn->panDstBands = static_cast<int *>(
305  CPLMalloc( sizeof( int ) * psOptionsIn->nBandCount ) );
306 
307  for ( int i = 0; i < psOptionsIn->nBandCount; i++ )
308  {
309  psOptionsIn->panSrcBands[i] = i + 1;
310  psOptionsIn->panDstBands[i] = i + 1;
311  }
312 }
313 
314 static void InitNoData( int nBandCount, double **ppdNoDataReal, double dDataReal )
315 {
316  if ( nBandCount <= 0 ) { return; }
317  if ( *ppdNoDataReal != nullptr ) { return; }
318 
319  *ppdNoDataReal = static_cast<double *>(
320  CPLMalloc( sizeof( double ) * nBandCount ) );
321 
322  for ( int i = 0; i < nBandCount; ++i )
323  {
324  ( *ppdNoDataReal )[i] = dDataReal;
325  }
326 }
327 
328 static void GDALWarpInitNoDataReal( GDALWarpOptions *psOptionsIn, double dNoDataReal )
329 {
330  InitNoData( psOptionsIn->nBandCount, &psOptionsIn->padfDstNoDataReal, dNoDataReal );
331  InitNoData( psOptionsIn->nBandCount, &psOptionsIn->padfSrcNoDataReal, dNoDataReal );
332  // older GDAL also requires imaginary values to be set
333  InitNoData( psOptionsIn->nBandCount, &psOptionsIn->padfDstNoDataImag, 0 );
334  InitNoData( psOptionsIn->nBandCount, &psOptionsIn->padfSrcNoDataImag, 0 );
335 }
336 #endif
337 
338 #if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,2,0)
339 
340 GDALDatasetH GDALAutoCreateWarpedVRTEx( GDALDatasetH hSrcDS, const char *pszSrcWKT, const char *pszDstWKT, GDALResampleAlg eResampleAlg,
341  double dfMaxError, const GDALWarpOptions *psOptionsIn, char **papszTransformerOptions )
342 {
343  VALIDATE_POINTER1( hSrcDS, "GDALAutoCreateWarpedVRT", nullptr );
344 
345  /* -------------------------------------------------------------------- */
346  /* Populate the warp options. */
347  /* -------------------------------------------------------------------- */
348  GDALWarpOptions *psWO = nullptr;
349  if ( psOptionsIn != nullptr )
350  psWO = GDALCloneWarpOptions( psOptionsIn );
351  else
352  psWO = GDALCreateWarpOptions();
353 
354  psWO->eResampleAlg = eResampleAlg;
355 
356  psWO->hSrcDS = hSrcDS;
357 
358  GDALWarpInitDefaultBandMapping( psWO, GDALGetRasterCount( hSrcDS ) );
359 
360  /* -------------------------------------------------------------------- */
361  /* Setup no data values */
362  /* -------------------------------------------------------------------- */
363  for ( int i = 0; i < psWO->nBandCount; i++ )
364  {
365  GDALRasterBandH rasterBand = GDALGetRasterBand( psWO->hSrcDS, psWO->panSrcBands[i] );
366 
367  int hasNoDataValue;
368  double noDataValue = GDALGetRasterNoDataValue( rasterBand, &hasNoDataValue );
369 
370  if ( hasNoDataValue )
371  {
372  // Check if the nodata value is out of range
373  int bClamped = FALSE;
374  int bRounded = FALSE;
375  CPL_IGNORE_RET_VAL(
376  GDALAdjustValueToDataType( GDALGetRasterDataType( rasterBand ),
377  noDataValue, &bClamped, &bRounded ) );
378  if ( !bClamped )
379  {
380  GDALWarpInitNoDataReal( psWO, -1e10 );
381 
382  psWO->padfSrcNoDataReal[i] = noDataValue;
383  psWO->padfDstNoDataReal[i] = noDataValue;
384  }
385  }
386  }
387 
388  if ( psWO->padfDstNoDataReal != nullptr )
389  {
390  if ( CSLFetchNameValue( psWO->papszWarpOptions, "INIT_DEST" ) == nullptr )
391  {
392  psWO->papszWarpOptions =
393  CSLSetNameValue( psWO->papszWarpOptions, "INIT_DEST", "NO_DATA" );
394  }
395  }
396 
397  /* -------------------------------------------------------------------- */
398  /* Create the transformer. */
399  /* -------------------------------------------------------------------- */
400  psWO->pfnTransformer = GDALGenImgProjTransform;
401 
402  char **papszOptions = nullptr;
403  if ( pszSrcWKT != nullptr )
404  papszOptions = CSLSetNameValue( papszOptions, "SRC_SRS", pszSrcWKT );
405  if ( pszDstWKT != nullptr )
406  papszOptions = CSLSetNameValue( papszOptions, "DST_SRS", pszDstWKT );
407  papszOptions = CSLMerge( papszOptions, papszTransformerOptions );
408  psWO->pTransformerArg =
409  GDALCreateGenImgProjTransformer2( psWO->hSrcDS, nullptr,
410  papszOptions );
411  CSLDestroy( papszOptions );
412 
413  if ( psWO->pTransformerArg == nullptr )
414  {
415  GDALDestroyWarpOptions( psWO );
416  return nullptr;
417  }
418 
419  /* -------------------------------------------------------------------- */
420  /* Figure out the desired output bounds and resolution. */
421  /* -------------------------------------------------------------------- */
422  double adfDstGeoTransform[6] = { 0.0 };
423  int nDstPixels = 0;
424  int nDstLines = 0;
425  CPLErr eErr =
426  GDALSuggestedWarpOutput( hSrcDS, psWO->pfnTransformer,
427  psWO->pTransformerArg,
428  adfDstGeoTransform, &nDstPixels, &nDstLines );
429  if ( eErr != CE_None )
430  {
431  GDALDestroyTransformer( psWO->pTransformerArg );
432  GDALDestroyWarpOptions( psWO );
433  return nullptr;
434  }
435 
436  /* -------------------------------------------------------------------- */
437  /* Update the transformer to include an output geotransform */
438  /* back to pixel/line coordinates. */
439  /* */
440  /* -------------------------------------------------------------------- */
441  GDALSetGenImgProjTransformerDstGeoTransform(
442  psWO->pTransformerArg, adfDstGeoTransform );
443 
444  /* -------------------------------------------------------------------- */
445  /* Do we want to apply an approximating transformation? */
446  /* -------------------------------------------------------------------- */
447  if ( dfMaxError > 0.0 )
448  {
449  psWO->pTransformerArg =
450  GDALCreateApproxTransformer( psWO->pfnTransformer,
451  psWO->pTransformerArg,
452  dfMaxError );
453  psWO->pfnTransformer = GDALApproxTransform;
454  GDALApproxTransformerOwnsSubtransformer( psWO->pTransformerArg, TRUE );
455  }
456 
457  /* -------------------------------------------------------------------- */
458  /* Create the VRT file. */
459  /* -------------------------------------------------------------------- */
460  GDALDatasetH hDstDS
461  = GDALCreateWarpedVRT( hSrcDS, nDstPixels, nDstLines,
462  adfDstGeoTransform, psWO );
463 
464  GDALDestroyWarpOptions( psWO );
465 
466  if ( pszDstWKT != nullptr )
467  GDALSetProjection( hDstDS, pszDstWKT );
468  else if ( pszSrcWKT != nullptr )
469  GDALSetProjection( hDstDS, pszSrcWKT );
470  else if ( GDALGetGCPCount( hSrcDS ) > 0 )
471  GDALSetProjection( hDstDS, GDALGetGCPProjection( hSrcDS ) );
472  else
473  GDALSetProjection( hDstDS, GDALGetProjectionRef( hSrcDS ) );
474 
475  return hDstDS;
476 }
477 #endif
478 
479 
481  GDALDatasetH hSrcDS,
482  const char *pszSrcWKT,
483  const char *pszDstWKT,
484  GDALResampleAlg eResampleAlg,
485  double dfMaxError,
486  const GDALWarpOptions *psOptionsIn )
487 {
488  char **opts = nullptr;
489  if ( GDALGetMetadata( hSrcDS, "RPC" ) )
490  {
491  // well-behaved RPC should have height offset a good value for RPC_HEIGHT
492  const char *heightOffStr = GDALGetMetadataItem( hSrcDS, "HEIGHT_OFF", "RPC" );
493  if ( heightOffStr )
494  opts = CSLAddNameValue( opts, "RPC_HEIGHT", heightOffStr );
495  }
496 
497  return GDALAutoCreateWarpedVRTEx( hSrcDS, pszSrcWKT, pszDstWKT, eResampleAlg, dfMaxError, psOptionsIn, opts );
498 }
499 
500 void *QgsGdalUtils::rpcAwareCreateTransformer( GDALDatasetH hSrcDS, GDALDatasetH hDstDS, char **papszOptions )
501 {
502  char **opts = CSLDuplicate( papszOptions );
503  if ( GDALGetMetadata( hSrcDS, "RPC" ) )
504  {
505  // well-behaved RPC should have height offset a good value for RPC_HEIGHT
506  const char *heightOffStr = GDALGetMetadataItem( hSrcDS, "HEIGHT_OFF", "RPC" );
507  if ( heightOffStr )
508  opts = CSLAddNameValue( opts, "RPC_HEIGHT", heightOffStr );
509  }
510  void *transformer = GDALCreateGenImgProjTransformer2( hSrcDS, hDstDS, opts );
511  CSLDestroy( opts );
512  return transformer;
513 }
514 
515 #ifndef QT_NO_NETWORKPROXY
517 {
518  // Check proxy configuration, they are application level but
519  // instead of adding an API and complex signal/slot connections
520  // given the limited cost of checking them on every provider instantiation
521  // we can do it here so that new settings are applied whenever a new layer
522  // is created.
523  QgsSettings settings;
524  // Check that proxy is enabled
525  if ( settings.value( QStringLiteral( "proxy/proxyEnabled" ), false ).toBool() )
526  {
527  // Get the first configured proxy
528  QList<QNetworkProxy> proxies( QgsNetworkAccessManager::instance()->proxyFactory()->queryProxy( ) );
529  if ( ! proxies.isEmpty() )
530  {
531  QNetworkProxy proxy( proxies.first() );
532  // TODO/FIXME: check excludes (the GDAL config options are global, we need a per-connection config option)
533  //QStringList excludes;
534  //excludes = settings.value( QStringLiteral( "proxy/proxyExcludedUrls" ), "" ).toStringList();
535 
536  QString proxyHost( proxy.hostName() );
537  qint16 proxyPort( proxy.port() );
538 
539  QString proxyUser( proxy.user() );
540  QString proxyPassword( proxy.password() );
541 
542  if ( ! proxyHost.isEmpty() )
543  {
544  QString connection( proxyHost );
545  if ( proxyPort )
546  {
547  connection += ':' + QString::number( proxyPort );
548  }
549  CPLSetConfigOption( "GDAL_HTTP_PROXY", connection.toUtf8() );
550  if ( ! proxyUser.isEmpty( ) )
551  {
552  QString credentials( proxyUser );
553  if ( ! proxyPassword.isEmpty( ) )
554  {
555  credentials += ':' + proxyPassword;
556  }
557  CPLSetConfigOption( "GDAL_HTTP_PROXYUSERPWD", credentials.toUtf8() );
558  }
559  }
560  }
561  }
562 }
563 #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 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 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 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 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:167
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:177
double height() const SIP_HOLDGIL
Returns the height of the rectangle.
Definition: qgsrectangle.h:209
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
Definition: qgsrectangle.h:202
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.
std::unique_ptr< std::remove_pointer< GDALDatasetH >::type, GDALDatasetCloser > dataset_unique_ptr
Scoped GDAL dataset.
Definition: qgsogrutils.h:134
std::unique_ptr< GDALWarpOptions, GDALWarpOptionsDeleter > warp_options_unique_ptr
Scoped GDAL warp options.
Definition: qgsogrutils.h:149
void * GDALDatasetH
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
const QgsCoordinateReferenceSystem & crs