24#define CPL_SUPRESS_CPLUSPLUS
26#include "gdalwarper.h"
27#include "cpl_string.h"
29#include <QNetworkProxy>
38 if ( node->eType != CXT_Element || !EQUAL( node->pszValue,
"Option" ) )
41 const QString optionName( CPLGetXMLValue( node,
"name",
nullptr ) );
42 if ( optionName.isEmpty() )
46 option.
name = optionName;
48 option.
description = QString( CPLGetXMLValue( node,
"description",
nullptr ) );
49 option.
scope = QString( CPLGetXMLValue( node,
"scope",
nullptr ) );
53 const char *pszType = CPLGetXMLValue( node,
"type",
nullptr );
54 const char *pszDefault = CPLGetXMLValue( node,
"default",
nullptr );
55 if ( pszType && EQUAL( pszType,
"string-select" ) )
58 for (
auto psOption = node->psChild; psOption !=
nullptr; psOption = psOption->psNext )
60 if ( psOption->eType != CXT_Element ||
61 !EQUAL( psOption->pszValue,
"Value" ) ||
62 psOption->psChild == nullptr )
66 option.
options << psOption->psChild->pszValue;
71 else if ( pszType && EQUAL( pszType,
"boolean" ) )
74 option.
defaultValue = pszDefault ? QString( pszDefault ) : QStringLiteral(
"YES" );
77 else if ( pszType && EQUAL( pszType,
"string" ) )
84 else if ( pszType && ( EQUAL( pszType,
"int" ) || EQUAL( pszType,
"integer" ) ) )
90 const int defaultInt = QString( pszDefault ).toInt( &ok );
95 if (
const char *pszMin = CPLGetXMLValue( node,
"min",
nullptr ) )
98 const int minInt = QString( pszMin ).toInt( &ok );
102 if (
const char *pszMax = CPLGetXMLValue( node,
"max",
nullptr ) )
105 const int maxInt = QString( pszMax ).toInt( &ok );
111 else if ( pszType && EQUAL( pszType,
"double" ) )
117 const double defaultDouble = QString( pszDefault ).toDouble( &ok );
122 if (
const char *pszMin = CPLGetXMLValue( node,
"min",
nullptr ) )
125 const double minDouble = QString( pszMin ).toDouble( &ok );
129 if (
const char *pszMax = CPLGetXMLValue( node,
"max",
nullptr ) )
132 const double maxDouble = QString( pszMax ).toDouble( &ok );
139 QgsDebugError( QStringLiteral(
"Unhandled GDAL option type: %1" ).arg( pszType ) );
145 QList< QgsGdalOption >
options;
146 for (
auto psItem = node->psChild; psItem !=
nullptr; psItem = psItem->psNext )
164 const QString driverShortName = GDALGetDriverShortName( driver );
165 if ( driverShortName == QLatin1String(
"SQLite" ) )
170 return GDALGetMetadataItem( driver, GDAL_DCAP_CREATE,
nullptr ) &&
171 GDALGetMetadataItem( driver, GDAL_DCAP_RASTER,
nullptr );
181 GDALDriverH hDriverMem = GDALGetDriverByName(
"MEM" );
189 const double cellSizeX = extent.
width() / width;
190 const double cellSizeY = extent.
height() / height;
191 double geoTransform[6];
192 geoTransform[0] = extent.
xMinimum();
193 geoTransform[1] = cellSizeX;
195 geoTransform[3] = extent.
yMinimum() + ( cellSizeY * height );
197 geoTransform[5] = -cellSizeY;
200 GDALSetGeoTransform( hSrcDS.get(), geoTransform );
206 const double cellSizeX = extent.
width() / width;
207 const double cellSizeY = extent.
height() / height;
208 double geoTransform[6];
209 geoTransform[0] = extent.
xMinimum();
210 geoTransform[1] = cellSizeX;
212 geoTransform[3] = extent.
yMinimum() + ( cellSizeY * height );
214 geoTransform[5] = -cellSizeY;
216 GDALDriverH hDriver = GDALGetDriverByName(
"GTiff" );
223 gdal::dataset_unique_ptr hDstDS( GDALCreate( hDriver, filename.toUtf8().constData(), width, height, 1, dataType,
nullptr ) );
231 GDALSetGeoTransform( hDstDS.get(), geoTransform );
237 if ( image.isNull() )
240 const QRgb *rgb =
reinterpret_cast<const QRgb *
>( image.constBits() );
241 GDALDriverH hDriverMem = GDALGetDriverByName(
"MEM" );
246 gdal::dataset_unique_ptr hSrcDS( GDALCreate( hDriverMem,
"", image.width(), image.height(), 0, GDT_Byte,
nullptr ) );
249 << QStringLiteral(
"PIXELOFFSET=%1" ).arg(
sizeof( QRgb ) )
250 << QStringLiteral(
"LINEOFFSET=%1" ).arg( image.bytesPerLine() )
251 << QStringLiteral(
"DATAPOINTER=%1" ).arg(
reinterpret_cast< qulonglong
>( rgb ) + 2 ) );
252 GDALAddBand( hSrcDS.get(), GDT_Byte, papszOptions );
253 CSLDestroy( papszOptions );
256 << QStringLiteral(
"PIXELOFFSET=%1" ).arg(
sizeof( QRgb ) )
257 << QStringLiteral(
"LINEOFFSET=%1" ).arg( image.bytesPerLine() )
258 << QStringLiteral(
"DATAPOINTER=%1" ).arg(
reinterpret_cast< qulonglong
>( rgb ) + 1 ) );
259 GDALAddBand( hSrcDS.get(), GDT_Byte, papszOptions );
260 CSLDestroy( papszOptions );
263 << QStringLiteral(
"PIXELOFFSET=%1" ).arg(
sizeof( QRgb ) )
264 << QStringLiteral(
"LINEOFFSET=%1" ).arg( image.bytesPerLine() )
265 << QStringLiteral(
"DATAPOINTER=%1" ).arg(
reinterpret_cast< qulonglong
>( rgb ) ) );
266 GDALAddBand( hSrcDS.get(), GDT_Byte, papszOptions );
267 CSLDestroy( papszOptions );
270 << QStringLiteral(
"PIXELOFFSET=%1" ).arg(
sizeof( QRgb ) )
271 << QStringLiteral(
"LINEOFFSET=%1" ).arg( image.bytesPerLine() )
272 << QStringLiteral(
"DATAPOINTER=%1" ).arg(
reinterpret_cast< qulonglong
>( rgb ) + 3 ) );
273 GDALAddBand( hSrcDS.get(), GDT_Byte, papszOptions );
274 CSLDestroy( papszOptions );
284 GDALDriverH hDriverMem = GDALGetDriverByName(
"MEM" );
288 const double cellSizeX = extent.
width() / pixelWidth;
289 const double cellSizeY = extent.
height() / pixelHeight;
290 double geoTransform[6];
291 geoTransform[0] = extent.
xMinimum();
292 geoTransform[1] = cellSizeX;
294 geoTransform[3] = extent.
yMinimum() + ( cellSizeY * pixelHeight );
296 geoTransform[5] = -cellSizeY;
300 int dataTypeSize = GDALGetDataTypeSizeBytes( dataType );
302 << QStringLiteral(
"PIXELOFFSET=%1" ).arg( dataTypeSize )
303 << QStringLiteral(
"LINEOFFSET=%1" ).arg( pixelWidth * dataTypeSize )
304 << QStringLiteral(
"DATAPOINTER=%1" ).arg(
reinterpret_cast< qulonglong
>( block ) ) );
305 GDALAddBand( hDstDS.get(), dataType, papszOptions );
306 CSLDestroy( papszOptions );
308 GDALSetGeoTransform( hDstDS.get(), geoTransform );
321 GDALRasterBandH band = GDALGetRasterBand( ret.get(), 1 );
323 GDALSetRasterNoDataValue( band, block->
noDataValue() );
340 GDALDriverH hDriverMem = GDALGetDriverByName(
"MEM" );
344 const double cellSizeX = gridXSize / block->
width();
345 const double cellSizeY = gridYSize / block->
height();
346 double geoTransform[6];
347 geoTransform[0] = origin.
x();
348 geoTransform[1] = cellSizeX * std::cos( rotation );
349 geoTransform[2] = cellSizeY * std::sin( rotation );
350 geoTransform[3] = origin.
y();
351 geoTransform[4] = cellSizeX * std::sin( rotation );
352 geoTransform[5] = -cellSizeY * std::cos( rotation );
357 int dataTypeSize = GDALGetDataTypeSizeBytes( dataType );
359 << QStringLiteral(
"PIXELOFFSET=%1" ).arg( dataTypeSize )
360 << QStringLiteral(
"LINEOFFSET=%1" ).arg( block->
width() * dataTypeSize )
361 << QStringLiteral(
"DATAPOINTER=%1" ).arg(
reinterpret_cast< qulonglong
>( block->
bits() ) ) );
362 GDALAddBand( hDstDS.get(), dataType, papszOptions );
363 CSLDestroy( papszOptions );
365 GDALSetGeoTransform( hDstDS.get(), geoTransform );
367 GDALRasterBandH band = GDALGetRasterBand( hDstDS.get(), 1 );
369 GDALSetRasterNoDataValue( band, block->
noDataValue() );
374static bool resampleSingleBandRasterStatic(
GDALDatasetH hSrcDS,
GDALDatasetH hDstDS, GDALResampleAlg resampleAlg,
char **papszOptions )
377 psWarpOptions->hSrcDS = hSrcDS;
378 psWarpOptions->hDstDS = hDstDS;
380 psWarpOptions->nBandCount = 1;
381 psWarpOptions->panSrcBands =
reinterpret_cast< int *
>( CPLMalloc(
sizeof(
int ) * 1 ) );
382 psWarpOptions->panDstBands =
reinterpret_cast< int *
>( CPLMalloc(
sizeof(
int ) * 1 ) );
383 psWarpOptions->panSrcBands[0] = 1;
384 psWarpOptions->panDstBands[0] = 1;
385 double noDataValue = GDALGetRasterNoDataValue( GDALGetRasterBand( hDstDS, 1 ),
nullptr );
386 psWarpOptions->padfDstNoDataReal =
reinterpret_cast< double *
>( CPLMalloc(
sizeof(
double ) * 1 ) );
387 psWarpOptions->padfDstNoDataReal[0] = noDataValue;
388 psWarpOptions->eResampleAlg = resampleAlg;
391 psWarpOptions->pTransformerArg = GDALCreateGenImgProjTransformer2( hSrcDS, hDstDS, papszOptions );
393 if ( ! psWarpOptions->pTransformerArg )
398 psWarpOptions->pfnTransformer = GDALGenImgProjTransform;
399 psWarpOptions->papszWarpOptions = CSLSetNameValue( psWarpOptions-> papszWarpOptions,
"INIT_DEST",
"NO_DATA" );
403 GDALWarpOperation oOperation;
404 CPLErr initResult = oOperation.Initialize( psWarpOptions.get() );
405 if ( initResult != CE_Failure )
406 retVal = oOperation.ChunkAndWarpImage( 0, 0, GDALGetRasterXSize( hDstDS ), GDALGetRasterYSize( hDstDS ) ) == CE_None;
407 GDALDestroyGenImgProjTransformer( psWarpOptions->pTransformerArg );
413 char **papszOptions =
nullptr;
414 if ( pszCoordinateOperation !=
nullptr )
415 papszOptions = CSLSetNameValue( papszOptions,
"COORDINATE_OPERATION", pszCoordinateOperation );
417 bool result = resampleSingleBandRasterStatic( hSrcDS, hDstDS, resampleAlg, papszOptions );
418 CSLDestroy( papszOptions );
424 GDALResampleAlg resampleAlg,
428 char **papszOptions =
nullptr;
433 bool result = resampleSingleBandRasterStatic( hSrcDS, hDstDS, resampleAlg, papszOptions );
434 CSLDestroy( papszOptions );
444 GDALRasterIOExtraArg extra;
445 INIT_RASTERIO_EXTRA_ARG( extra );
446 extra.eResampleAlg = resampleAlg;
448 QImage res( outputSize, image.format() );
452 GByte *rgb =
reinterpret_cast<GByte *
>( res.bits() );
454 CPLErr err = GDALRasterIOEx( GDALGetRasterBand( srcDS.get(), 1 ), GF_Read, 0, 0, image.width(), image.height(), rgb + 2, outputSize.width(),
455 outputSize.height(), GDT_Byte,
sizeof( QRgb ), res.bytesPerLine(), &extra );
456 if ( err != CE_None )
458 QgsDebugError( QStringLiteral(
"failed to read red band" ) );
462 err = GDALRasterIOEx( GDALGetRasterBand( srcDS.get(), 2 ), GF_Read, 0, 0, image.width(), image.height(), rgb + 1, outputSize.width(),
463 outputSize.height(), GDT_Byte,
sizeof( QRgb ), res.bytesPerLine(), &extra );
464 if ( err != CE_None )
466 QgsDebugError( QStringLiteral(
"failed to read green band" ) );
470 err = GDALRasterIOEx( GDALGetRasterBand( srcDS.get(), 3 ), GF_Read, 0, 0, image.width(), image.height(), rgb, outputSize.width(),
471 outputSize.height(), GDT_Byte,
sizeof( QRgb ), res.bytesPerLine(), &extra );
472 if ( err != CE_None )
474 QgsDebugError( QStringLiteral(
"failed to read blue band" ) );
478 err = GDALRasterIOEx( GDALGetRasterBand( srcDS.get(), 4 ), GF_Read, 0, 0, image.width(), image.height(), rgb + 3, outputSize.width(),
479 outputSize.height(), GDT_Byte,
sizeof( QRgb ), res.bytesPerLine(), &extra );
480 if ( err != CE_None )
482 QgsDebugError( QStringLiteral(
"failed to read alpha band" ) );
492 GDALDriverH myGdalDriver = GDALGetDriverByName( format.toLocal8Bit().constData() );
496 char **GDALmetadata = GDALGetMetadata( myGdalDriver,
nullptr );
497 message += QLatin1String(
"Format Details:\n" );
498 message += QStringLiteral(
" Extension: %1\n" ).arg( CSLFetchNameValue( GDALmetadata, GDAL_DMD_EXTENSION ) );
499 message += QStringLiteral(
" Short Name: %1" ).arg( GDALGetDriverShortName( myGdalDriver ) );
500 message += QStringLiteral(
" / Long Name: %1\n" ).arg( GDALGetDriverLongName( myGdalDriver ) );
501 message += QStringLiteral(
" Help page: http://www.gdal.org/%1\n\n" ).arg( CSLFetchNameValue( GDALmetadata, GDAL_DMD_HELPTOPIC ) );
505 CPLXMLNode *psCOL = CPLParseXMLString( GDALGetMetadataItem( myGdalDriver,
506 GDAL_DMD_CREATIONOPTIONLIST,
"" ) );
507 char *pszFormattedXML = CPLSerializeXMLTree( psCOL );
508 if ( pszFormattedXML )
509 message += QString( pszFormattedXML );
511 CPLDestroyXMLNode( psCOL );
512 if ( pszFormattedXML )
513 CPLFree( pszFormattedXML );
520 char **papszRetList =
nullptr;
521 const auto constList = list;
522 for (
const QString &elem : constList )
524 papszRetList = CSLAddString( papszRetList, elem.toLocal8Bit().constData() );
531 GDALDriverH myGdalDriver = GDALGetDriverByName( format.toLocal8Bit().constData() );
532 if ( ! myGdalDriver )
533 return QStringLiteral(
"invalid GDAL driver" );
537 const int ok = GDALValidateCreationOptions( myGdalDriver, papszOptions );
538 CSLDestroy( papszOptions );
541 return QStringLiteral(
"Failed GDALValidateCreationOptions() test" );
547 const char *pszSrcWKT,
548 const char *pszDstWKT,
549 GDALResampleAlg eResampleAlg,
551 const GDALWarpOptions *psOptionsIn )
553 char **opts =
nullptr;
554 if ( GDALGetMetadata( hSrcDS,
"RPC" ) )
557 const char *heightOffStr = GDALGetMetadataItem( hSrcDS,
"HEIGHT_OFF",
"RPC" );
559 opts = CSLAddNameValue( opts,
"RPC_HEIGHT", heightOffStr );
562 return GDALAutoCreateWarpedVRTEx( hSrcDS, pszSrcWKT, pszDstWKT, eResampleAlg, dfMaxError, psOptionsIn, opts );
567 char **opts = CSLDuplicate( papszOptions );
568 if ( GDALGetMetadata( hSrcDS,
"RPC" ) )
571 const char *heightOffStr = GDALGetMetadataItem( hSrcDS,
"HEIGHT_OFF",
"RPC" );
573 opts = CSLAddNameValue( opts,
"RPC_HEIGHT", heightOffStr );
575 void *transformer = GDALCreateGenImgProjTransformer2( hSrcDS, hDstDS, opts );
585 return GDALDataType::GDT_Unknown;
588 return GDALDataType::GDT_Byte;
591#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,7,0)
592 return GDALDataType::GDT_Int8;
594 return GDALDataType::GDT_Unknown;
598 return GDALDataType::GDT_UInt16;
601 return GDALDataType::GDT_Int16;
604 return GDALDataType::GDT_UInt32;
607 return GDALDataType::GDT_Int32;
610 return GDALDataType::GDT_Float32;
613 return GDALDataType::GDT_Float64;
616 return GDALDataType::GDT_CInt16;
619 return GDALDataType::GDT_CInt32;
622 return GDALDataType::GDT_CFloat32;
625 return GDALDataType::GDT_CFloat64;
629 return GDALDataType::GDT_Unknown;
633 return GDALDataType::GDT_Unknown;
638 GDALResampleAlg eResampleAlg = GRA_NearestNeighbour;
643 eResampleAlg = GRA_NearestNeighbour;
647 eResampleAlg = GRA_Bilinear;
651 eResampleAlg = GRA_Cubic;
655 eResampleAlg = GRA_CubicSpline;
659 eResampleAlg = GRA_Lanczos;
663 eResampleAlg = GRA_Average;
667 eResampleAlg = GRA_Mode;
674#ifndef QT_NO_NETWORKPROXY
684 if ( settings.
value( QStringLiteral(
"proxy/proxyEnabled" ),
false ).toBool() )
688 if ( ! proxies.isEmpty() )
690 const QNetworkProxy proxy( proxies.first() );
695 const QString proxyHost( proxy.hostName() );
696 const quint16 proxyPort( proxy.port() );
698 const QString proxyUser( proxy.user() );
699 const QString proxyPassword( proxy.password() );
701 if ( ! proxyHost.isEmpty() )
703 QString connection( proxyHost );
706 connection +=
':' + QString::number( proxyPort );
708 CPLSetConfigOption(
"GDAL_HTTP_PROXY", connection.toUtf8() );
709 if ( ! proxyUser.isEmpty( ) )
711 QString credentials( proxyUser );
712 if ( ! proxyPassword.isEmpty( ) )
714 credentials +=
':' + proxyPassword;
716 CPLSetConfigOption(
"GDAL_HTTP_PROXYUSERPWD", credentials.toUtf8() );
725 const QFileInfo info( path );
726 const long long size = info.size();
732 const QString suffix = info.suffix().toLower();
733 static const QStringList sFileSizeDependentExtensions
735 QStringLiteral(
"xlsx" ),
736 QStringLiteral(
"ods" ),
737 QStringLiteral(
"csv" )
739 if ( sFileSizeDependentExtensions.contains( suffix ) )
742 return size < smallFileSizeLimit;
752#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,4,0)
754 static std::once_flag initialized;
755 static QStringList SUPPORTED_DB_LAYERS_EXTENSIONS;
756 std::call_once( initialized, [ = ]
760 GDALDriverH driver =
nullptr;
762 QSet< QString > extensions;
764 for (
int i = 0; i < GDALGetDriverCount(); ++i )
766 driver = GDALGetDriver( i );
773 bool isMultiLayer =
false;
774 if ( QString( GDALGetMetadataItem( driver, GDAL_DCAP_RASTER,
nullptr ) ) == QLatin1String(
"YES" ) )
776 if ( GDALGetMetadataItem( driver, GDAL_DMD_SUBDATASETS,
nullptr ) !=
nullptr )
781 if ( !isMultiLayer && QString( GDALGetMetadataItem( driver, GDAL_DCAP_VECTOR,
nullptr ) ) == QLatin1String(
"YES" ) )
783 if ( GDALGetMetadataItem( driver, GDAL_DCAP_MULTIPLE_VECTOR_LAYERS,
nullptr ) !=
nullptr )
792 const QString driverExtensions = GDALGetMetadataItem( driver, GDAL_DMD_EXTENSIONS,
"" );
793 if ( driverExtensions.isEmpty() )
796 const QStringList splitExtensions = driverExtensions.split(
' ', Qt::SkipEmptyParts );
798 for (
const QString &ext : splitExtensions )
801 if ( ext == QLatin1String(
"tif" ) || ext == QLatin1String(
"tiff" ) )
804 extensions.insert( ext );
808 SUPPORTED_DB_LAYERS_EXTENSIONS = QStringList( extensions.constBegin(), extensions.constEnd() );
810 return SUPPORTED_DB_LAYERS_EXTENSIONS;
813 static const QStringList SUPPORTED_DB_LAYERS_EXTENSIONS
815 QStringLiteral(
"gpkg" ),
816 QStringLiteral(
"sqlite" ),
817 QStringLiteral(
"db" ),
818 QStringLiteral(
"gdb" ),
819 QStringLiteral(
"kml" ),
820 QStringLiteral(
"kmz" ),
821 QStringLiteral(
"osm" ),
822 QStringLiteral(
"mdb" ),
823 QStringLiteral(
"accdb" ),
824 QStringLiteral(
"xls" ),
825 QStringLiteral(
"xlsx" ),
826 QStringLiteral(
"ods" ),
827 QStringLiteral(
"gpx" ),
828 QStringLiteral(
"pdf" ),
829 QStringLiteral(
"pbf" ),
830 QStringLiteral(
"vrt" ),
831 QStringLiteral(
"nc" ),
832 QStringLiteral(
"dxf" ),
833 QStringLiteral(
"shp.zip" ) };
834 return SUPPORTED_DB_LAYERS_EXTENSIONS;
842 const thread_local QRegularExpression vsiRx( QStringLiteral(
"^(/vsi.+?/)" ), QRegularExpression::PatternOption::CaseInsensitiveOption );
843 const QRegularExpressionMatch vsiMatch = vsiRx.match( path );
844 if ( vsiMatch.hasMatch() )
845 return vsiMatch.captured( 1 );
847 if ( path.endsWith( QLatin1String(
".shp.zip" ), Qt::CaseInsensitive ) )
850 if ( GDALIdentifyDriverEx( path.toUtf8().constData(), GDAL_OF_VECTOR,
nullptr,
nullptr ) )
852 return QStringLiteral(
"/vsizip/" );
854 else if ( path.endsWith( QLatin1String(
".zip" ), Qt::CaseInsensitive ) )
855 return QStringLiteral(
"/vsizip/" );
856 else if ( path.endsWith( QLatin1String(
".tar" ), Qt::CaseInsensitive ) ||
857 path.endsWith( QLatin1String(
".tar.gz" ), Qt::CaseInsensitive ) ||
858 path.endsWith( QLatin1String(
".tgz" ), Qt::CaseInsensitive ) )
859 return QStringLiteral(
"/vsitar/" );
860 else if ( path.endsWith( QLatin1String(
".gz" ), Qt::CaseInsensitive ) )
861 return QStringLiteral(
"/vsigzip/" );
862#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,7,0)
863 else if ( vsiPrefixes.contains( QStringLiteral(
"/vsi7z/" ) ) &&
864 ( path.endsWith( QLatin1String(
".7z" ), Qt::CaseInsensitive ) ||
865 path.endsWith( QLatin1String(
".lpk" ), Qt::CaseInsensitive ) ||
866 path.endsWith( QLatin1String(
".lpkx" ), Qt::CaseInsensitive ) ||
867 path.endsWith( QLatin1String(
".mpk" ), Qt::CaseInsensitive ) ||
868 path.endsWith( QLatin1String(
".mpkx" ), Qt::CaseInsensitive ) ) )
869 return QStringLiteral(
"/vsi7z/" );
870 else if ( vsiPrefixes.contains( QStringLiteral(
"/vsirar/" ) ) &&
871 path.endsWith( QLatin1String(
".rar" ), Qt::CaseInsensitive ) )
872 return QStringLiteral(
"/vsirar/" );
880 QStringList res { QStringLiteral(
"/vsizip/" ),
881 QStringLiteral(
"/vsitar/" ),
882 QStringLiteral(
"/vsigzip/" ),
884#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,7,0)
885 res.append( QStringLiteral(
"/vsi7z/" ) );
886 res.append( QStringLiteral(
"/vsirar/" ) );
894 static std::once_flag initialized;
895 static QList<QgsGdalUtils::VsiNetworkFileSystemDetails> VSI_FILE_SYSTEM_DETAILS;
896 std::call_once( initialized, [ = ]
898 if (
char **papszPrefixes = VSIGetFileSystemsPrefixes() )
900 for (
int i = 0; papszPrefixes[i]; i++ )
903 details.
identifier = QString( papszPrefixes[i] );
909 if ( details.
identifier == QLatin1String(
"vsicurl" ) )
910 details.
name = QObject::tr(
"HTTP/HTTPS/FTP" );
911 else if ( details.
identifier == QLatin1String(
"vsis3" ) )
912 details.
name = QObject::tr(
"AWS S3" );
913 else if ( details.
identifier == QLatin1String(
"vsigs" ) )
914 details.
name = QObject::tr(
"Google Cloud Storage" );
915 else if ( details.
identifier == QLatin1String(
"vsiaz" ) )
916 details.
name = QObject::tr(
"Microsoft Azure Blob" );
917 else if ( details.
identifier == QLatin1String(
"vsiadls" ) )
918 details.
name = QObject::tr(
"Microsoft Azure Data Lake Storage" );
919 else if ( details.
identifier == QLatin1String(
"vsioss" ) )
920 details.
name = QObject::tr(
"Alibaba Cloud OSS" );
921 else if ( details.
identifier == QLatin1String(
"vsiswift" ) )
922 details.
name = QObject::tr(
"OpenStack Swift Object Storage" );
923 else if ( details.
identifier == QLatin1String(
"vsihdfs" ) )
924 details.
name = QObject::tr(
"Hadoop File System" );
927 VSI_FILE_SYSTEM_DETAILS.append( details );
930 CSLDestroy( papszPrefixes );
934 return VSI_FILE_SYSTEM_DETAILS;
944 QStringList res { QStringLiteral(
".zip" ),
945 QStringLiteral(
".tar" ),
946 QStringLiteral(
".tar.gz" ),
947 QStringLiteral(
".tgz" ),
948 QStringLiteral(
".gz" ),
950#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,7,0)
951 res.append( { QStringLiteral(
".7z" ),
952 QStringLiteral(
".lpk" ),
953 QStringLiteral(
".lpkx" ),
954 QStringLiteral(
".mpk" ),
955 QStringLiteral(
".mpkx" ),
956 QStringLiteral(
".rar" )
964 const QString extWithDot = extension.startsWith(
'.' ) ? extension : (
'.' + extension );
970 if ( prefix.isEmpty() )
973 QString vsiPrefix = prefix;
974 if ( vsiPrefix.startsWith(
'/' ) )
975 vsiPrefix = vsiPrefix.mid( 1 );
976 if ( vsiPrefix.endsWith(
'/' ) )
979 if ( !vsiPrefix.startsWith( QLatin1String(
"vsi" ) ) )
982 if ( vsiPrefix == QLatin1String(
"vsizip" ) ||
983 vsiPrefix == QLatin1String(
"vsigzip" ) ||
984 vsiPrefix == QLatin1String(
"vsitar" ) ||
985 vsiPrefix == QLatin1String(
"vsi7z" ) ||
986 vsiPrefix == QLatin1String(
"vsirar" ) )
989 else if ( vsiPrefix == QLatin1String(
"vsicurl" ) ||
990 vsiPrefix == QLatin1String(
"vsicurl_streaming" ) )
993 else if ( vsiPrefix == QLatin1String(
"vsis3" ) ||
994 vsiPrefix == QLatin1String(
"vsicurl_streaming" ) ||
995 vsiPrefix == QLatin1String(
"vsigs" ) ||
996 vsiPrefix == QLatin1String(
"vsigs_streaming" ) ||
997 vsiPrefix == QLatin1String(
"vsiaz" ) ||
998 vsiPrefix == QLatin1String(
"vsiaz_streaming" ) ||
999 vsiPrefix == QLatin1String(
"vsiadls" ) ||
1000 vsiPrefix == QLatin1String(
"vsioss" ) ||
1001 vsiPrefix == QLatin1String(
"vsioss_streaming" ) ||
1002 vsiPrefix == QLatin1String(
"vsiswift" ) ||
1003 vsiPrefix == QLatin1String(
"vsiswift_streaming" ) ||
1004 vsiPrefix == QLatin1String(
"vsihdfs" ) ||
1005 vsiPrefix == QLatin1String(
"vsiwebhdfs" ) )
1008 else if ( vsiPrefix == QLatin1String(
"vsimem" ) )
1016 CPLPushErrorHandler( CPLQuietErrorHandler );
1018 GDALDriverH hDriver =
nullptr;
1023 hDriver = GDALIdentifyDriverEx( vrtPath.toUtf8().constData(), GDAL_OF_VECTOR,
nullptr,
nullptr );
1027 hDriver = GDALIdentifyDriverEx( vrtPath.toUtf8().constData(), GDAL_OF_RASTER,
nullptr,
nullptr );
1040 CPLPopErrorHandler();
1041 return static_cast< bool >( hDriver );
1046 QString vsiPrefix = prefix;
1047 if ( !vsiPrefix.startsWith(
'/' ) )
1048 vsiPrefix.prepend(
'/' );
1049 if ( !vsiPrefix.endsWith(
'/' ) )
1050 vsiPrefix.append(
'/' );
1052 QString vsiPath = path;
1053 if ( vsiPath.endsWith(
'/' ) )
1056 const QString bucket = vsiPrefix + vsiPath;
1058 for (
auto it = options.constBegin(); it != options.constEnd(); ++it )
1060#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3, 6, 0)
1061 VSISetPathSpecificOption( bucket.toUtf8().constData(), it.key().toUtf8().constData(), it.value().toString().toUtf8().constData() );
1062#elif GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3, 5, 0)
1063 VSISetCredential( bucket.toUtf8().constData(), it.key().toUtf8().constData(), it.value().toString().toUtf8().constData() );
VsiHandlerType
GDAL VSI handler types.
@ Memory
In-memory types (e.g. vsimem)
@ Invalid
Invalid type, i.e. not a valid VSI handler.
@ Cloud
Specific cloud provider types (e.g. vsis3)
@ Archive
File archive type (e.g. vsizip)
@ Network
Generic network types (e.g. vsicurl)
@ Critical
Critical/error message.
DataType
Raster data types.
@ Float32
Thirty two bit floating point (float)
@ CFloat64
Complex Float64.
@ Int16
Sixteen bit signed integer (qint16)
@ ARGB32_Premultiplied
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32_Premultiplied.
@ Int8
Eight bit signed integer (qint8) (added in QGIS 3.30)
@ UInt16
Sixteen bit unsigned integer (quint16)
@ Byte
Eight bit unsigned integer (quint8)
@ UnknownDataType
Unknown or unspecified type.
@ ARGB32
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32.
@ Int32
Thirty two bit signed integer (qint32)
@ Float64
Sixty four bit floating point (double)
@ CFloat32
Complex Float32.
@ UInt32
Thirty two bit unsigned integer (quint32)
LayerType
Types of layers that can be added to a map.
@ Group
Composite group layer. Added in QGIS 3.24.
@ Plugin
Plugin based layer.
@ TiledScene
Tiled scene layer. Added in QGIS 3.34.
@ Annotation
Contains freeform, georeferenced annotations. Added in QGIS 3.16.
@ VectorTile
Vector tile layer. Added in QGIS 3.14.
@ Mesh
Mesh layer. Added in QGIS 3.2.
@ PointCloud
Point cloud layer. Added in QGIS 3.18.
@ PreferredGdal
Preferred format for conversion of CRS to WKT for use with the GDAL library.
This class represents a coordinate reference system (CRS).
QString toWkt(Qgis::CrsWktVariant variant=Qgis::CrsWktVariant::Wkt1Gdal, bool multiline=false, int indentationWidth=4) const
Returns a WKT representation of this CRS.
Encapsulates the definition of a GDAL configuration option.
QVariant defaultValue
Default value.
QVariant maximum
Maximum acceptable value.
QStringList options
Available choices, for Select options.
QVariant minimum
Minimum acceptable value.
@ Select
Selection option.
QString scope
Option scope.
static QList< QgsGdalOption > optionsFromXml(const CPLXMLNode *node)
Returns a list of all GDAL options from an XML node.
static QgsGdalOption fromXmlNode(const CPLXMLNode *node)
Creates a QgsGdalOption from an XML node.
QString description
Option description.
static Qgis::VsiHandlerType vsiHandlerType(const QString &prefix)
Returns the VSI handler type for a given VSI prefix.
static bool applyVsiCredentialOptions(const QString &prefix, const QString &path, const QVariantMap &options)
Attempts to apply VSI credential options.
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 vsiPrefixForPath(const QString &path)
Returns a the vsi prefix which corresponds to a file path, or an empty string if the path is not asso...
static QString helpCreationOptionsFormat(const QString &format)
Gets creation options metadata for a given format.
static bool vrtMatchesLayerType(const QString &vrtPath, Qgis::LayerType type)
Returns true if the VRT file at the specified path is a VRT matching the given layer type.
static GDALResampleAlg gdalResamplingAlgorithm(QgsRasterDataProvider::ResamplingMethod method)
Returns the GDAL resampling method corresponding to the QGIS resampling method.
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 bool isVsiArchiveFileExtension(const QString &extension)
Returns true if a file extension is a supported archive style container (e.g.
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 GDALDataType gdalDataTypeFromQgisDataType(Qgis::DataType dataType)
Returns the GDAL data type corresponding to the QGIS data type dataType.
static bool isVsiArchivePrefix(const QString &prefix)
Returns true if prefix is a supported archive style container prefix (e.g.
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 a data block to a single band GDAL memory dataset.
static QList< VsiNetworkFileSystemDetails > vsiNetworkFileSystems()
Returns a list of available GDAL VSI network file systems.
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 QStringList vsiArchiveFileExtensions()
Returns a list of file extensions which correspond to archive style containers supported by GDAL (e....
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 QStringList vsiArchivePrefixes()
Returns a list of vsi prefixes which correspond to archive style containers (eg vsizip).
static void warning(const QString &msg)
Goes to qWarning.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
static QgsNetworkAccessManager * instance(Qt::ConnectionType connectionType=Qt::BlockingQueuedConnection)
Returns a pointer to the active QgsNetworkAccessManager for the current thread.
A class to represent a 2D point.
int height() const
Returns the height (number of rows) of the raster block.
char * bits(int row, int column)
Returns a pointer to block data.
double noDataValue() const
Returns no data value.
Qgis::DataType dataType() const
Returns data type.
int width() const
Returns the width (number of columns) of the raster block.
ResamplingMethod
Resampling method for provider-level resampling.
@ Lanczos
Lanczos windowed sinc interpolation (6x6 kernel)
@ Nearest
Nearest-neighbour resampling.
@ Mode
Mode (selects the value which appears most often of all the sampled points)
@ Bilinear
Bilinear (2x2 kernel) resampling.
@ Average
Average resampling.
@ CubicSpline
Cubic B-Spline Approximation (4x4 kernel)
@ Cubic
Cubic Convolution Approximation (4x4 kernel) resampling.
A rectangle specified with double values.
double xMinimum() const
Returns the x minimum value (left side of rectangle).
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
double width() const
Returns the width of the rectangle.
double height() const
Returns the height of the rectangle.
This class is a composition of two QSettings instances:
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.
std::unique_ptr< GDALWarpOptions, GDALWarpOptionsDeleter > warp_options_unique_ptr
Scoped GDAL warp options.
#define QgsDebugError(str)
const QgsCoordinateReferenceSystem & crs
Encapsulates details for a GDAL VSI network file system.
QString name
Translated, user-friendly name.
QString identifier
VSI handler identifier, eg "vsis3".