25#define CPL_SUPRESS_CPLUSPLUS
27#include "gdalwarper.h"
28#include "cpl_string.h"
30#include <QNetworkProxy>
39 if ( node->eType != CXT_Element || !EQUAL( node->pszValue,
"Option" ) )
42 const QString optionName( CPLGetXMLValue( node,
"name",
nullptr ) );
43 if ( optionName.isEmpty() )
47 option.
name = optionName;
49 option.
description = QString( CPLGetXMLValue( node,
"description",
nullptr ) );
50 option.
scope = QString( CPLGetXMLValue( node,
"scope",
nullptr ) );
54 const char *pszType = CPLGetXMLValue( node,
"type",
nullptr );
55 const char *pszDefault = CPLGetXMLValue( node,
"default",
nullptr );
56 if ( pszType && EQUAL( pszType,
"string-select" ) )
59 for (
auto psOption = node->psChild; psOption !=
nullptr; psOption = psOption->psNext )
61 if ( psOption->eType != CXT_Element ||
62 !EQUAL( psOption->pszValue,
"Value" ) ||
67 option.
options << psOption->psChild->pszValue;
72 else if ( pszType && EQUAL( pszType,
"boolean" ) )
75 option.
defaultValue = pszDefault ? QString( pszDefault ) : QStringLiteral(
"YES" );
78 else if ( pszType && EQUAL( pszType,
"string" ) )
85 else if ( pszType && ( EQUAL( pszType,
"int" ) || EQUAL( pszType,
"integer" ) ) )
91 const int defaultInt = QString( pszDefault ).toInt( &ok );
96 if (
const char *pszMin = CPLGetXMLValue( node,
"min",
nullptr ) )
99 const int minInt = QString( pszMin ).toInt( &ok );
103 if (
const char *pszMax = CPLGetXMLValue( node,
"max",
nullptr ) )
106 const int maxInt = QString( pszMax ).toInt( &ok );
112 else if ( pszType && ( EQUAL( pszType,
"double" ) || EQUAL( pszType,
"float" ) ) )
118 const double defaultDouble = QString( pszDefault ).toDouble( &ok );
123 if (
const char *pszMin = CPLGetXMLValue( node,
"min",
nullptr ) )
126 const double minDouble = QString( pszMin ).toDouble( &ok );
130 if (
const char *pszMax = CPLGetXMLValue( node,
"max",
nullptr ) )
133 const double maxDouble = QString( pszMax ).toDouble( &ok );
140 QgsDebugError( QStringLiteral(
"Unhandled GDAL option type: %1" ).arg( pszType ) );
146 QList< QgsGdalOption >
options;
147 for (
auto psItem = node->psChild; psItem !=
nullptr; psItem = psItem->psNext )
165 const QString driverShortName = GDALGetDriverShortName( driver );
166 if ( driverShortName == QLatin1String(
"SQLite" ) ||
167 driverShortName == QLatin1String(
"PDF" ) )
172 return GDALGetMetadataItem( driver, GDAL_DCAP_CREATE,
nullptr ) &&
173 GDALGetMetadataItem( driver, GDAL_DCAP_RASTER,
nullptr );
183 GDALDriverH hDriverMem = GDALGetDriverByName(
"MEM" );
191 const double cellSizeX = extent.
width() / width;
192 const double cellSizeY = extent.
height() / height;
193 double geoTransform[6];
194 geoTransform[0] = extent.
xMinimum();
195 geoTransform[1] = cellSizeX;
197 geoTransform[3] = extent.
yMinimum() + ( cellSizeY * height );
199 geoTransform[5] = -cellSizeY;
202 GDALSetGeoTransform( hSrcDS.get(), geoTransform );
208 const double cellSizeX = extent.
width() / width;
209 const double cellSizeY = extent.
height() / height;
210 double geoTransform[6];
211 geoTransform[0] = extent.
xMinimum();
212 geoTransform[1] = cellSizeX;
214 geoTransform[3] = extent.
yMinimum() + ( cellSizeY * height );
216 geoTransform[5] = -cellSizeY;
218 GDALDriverH hDriver = GDALGetDriverByName(
"GTiff" );
225 gdal::dataset_unique_ptr hDstDS( GDALCreate( hDriver, filename.toUtf8().constData(), width, height, 1, dataType,
nullptr ) );
233 GDALSetGeoTransform( hDstDS.get(), geoTransform );
239 if ( image.isNull() )
242 const QRgb *rgb =
reinterpret_cast<const QRgb *
>( image.constBits() );
243 GDALDriverH hDriverMem = GDALGetDriverByName(
"MEM" );
248 gdal::dataset_unique_ptr hSrcDS( GDALCreate( hDriverMem,
"", image.width(), image.height(), 0, GDT_Byte,
nullptr ) );
251 << QStringLiteral(
"PIXELOFFSET=%1" ).arg(
sizeof( QRgb ) )
252 << QStringLiteral(
"LINEOFFSET=%1" ).arg( image.bytesPerLine() )
253 << QStringLiteral(
"DATAPOINTER=%1" ).arg(
reinterpret_cast< qulonglong
>( rgb ) + 2 ) );
254 GDALAddBand( hSrcDS.get(), GDT_Byte, papszOptions );
255 CSLDestroy( papszOptions );
258 << QStringLiteral(
"PIXELOFFSET=%1" ).arg(
sizeof( QRgb ) )
259 << QStringLiteral(
"LINEOFFSET=%1" ).arg( image.bytesPerLine() )
260 << QStringLiteral(
"DATAPOINTER=%1" ).arg(
reinterpret_cast< qulonglong
>( rgb ) + 1 ) );
261 GDALAddBand( hSrcDS.get(), GDT_Byte, papszOptions );
262 CSLDestroy( papszOptions );
265 << QStringLiteral(
"PIXELOFFSET=%1" ).arg(
sizeof( QRgb ) )
266 << QStringLiteral(
"LINEOFFSET=%1" ).arg( image.bytesPerLine() )
267 << QStringLiteral(
"DATAPOINTER=%1" ).arg(
reinterpret_cast< qulonglong
>( rgb ) ) );
268 GDALAddBand( hSrcDS.get(), GDT_Byte, papszOptions );
269 CSLDestroy( papszOptions );
272 << QStringLiteral(
"PIXELOFFSET=%1" ).arg(
sizeof( QRgb ) )
273 << QStringLiteral(
"LINEOFFSET=%1" ).arg( image.bytesPerLine() )
274 << QStringLiteral(
"DATAPOINTER=%1" ).arg(
reinterpret_cast< qulonglong
>( rgb ) + 3 ) );
275 GDALAddBand( hSrcDS.get(), GDT_Byte, papszOptions );
276 CSLDestroy( papszOptions );
286 GDALDriverH hDriverMem = GDALGetDriverByName(
"MEM" );
290 const double cellSizeX = extent.
width() / pixelWidth;
291 const double cellSizeY = extent.
height() / pixelHeight;
292 double geoTransform[6];
293 geoTransform[0] = extent.
xMinimum();
294 geoTransform[1] = cellSizeX;
296 geoTransform[3] = extent.
yMinimum() + ( cellSizeY * pixelHeight );
298 geoTransform[5] = -cellSizeY;
302 int dataTypeSize = GDALGetDataTypeSizeBytes( dataType );
304 << QStringLiteral(
"PIXELOFFSET=%1" ).arg( dataTypeSize )
305 << QStringLiteral(
"LINEOFFSET=%1" ).arg( pixelWidth * dataTypeSize )
306 << QStringLiteral(
"DATAPOINTER=%1" ).arg(
reinterpret_cast< qulonglong
>( block ) ) );
307 GDALAddBand( hDstDS.get(), dataType, papszOptions );
308 CSLDestroy( papszOptions );
310 GDALSetGeoTransform( hDstDS.get(), geoTransform );
323 GDALRasterBandH band = GDALGetRasterBand( ret.get(), 1 );
325 GDALSetRasterNoDataValue( band, block->
noDataValue() );
342 GDALDriverH hDriverMem = GDALGetDriverByName(
"MEM" );
346 const double cellSizeX = gridXSize / block->
width();
347 const double cellSizeY = gridYSize / block->
height();
348 double geoTransform[6];
349 geoTransform[0] = origin.
x();
350 geoTransform[1] = cellSizeX * std::cos( rotation );
351 geoTransform[2] = cellSizeY * std::sin( rotation );
352 geoTransform[3] = origin.
y();
353 geoTransform[4] = cellSizeX * std::sin( rotation );
354 geoTransform[5] = -cellSizeY * std::cos( rotation );
359 int dataTypeSize = GDALGetDataTypeSizeBytes( dataType );
361 << QStringLiteral(
"PIXELOFFSET=%1" ).arg( dataTypeSize )
362 << QStringLiteral(
"LINEOFFSET=%1" ).arg( block->
width() * dataTypeSize )
363 << QStringLiteral(
"DATAPOINTER=%1" ).arg(
reinterpret_cast< qulonglong
>( block->
bits() ) ) );
364 GDALAddBand( hDstDS.get(), dataType, papszOptions );
365 CSLDestroy( papszOptions );
367 GDALSetGeoTransform( hDstDS.get(), geoTransform );
369 GDALRasterBandH band = GDALGetRasterBand( hDstDS.get(), 1 );
371 GDALSetRasterNoDataValue( band, block->
noDataValue() );
376static bool resampleSingleBandRasterStatic(
GDALDatasetH hSrcDS,
GDALDatasetH hDstDS, GDALResampleAlg resampleAlg,
char **papszOptions )
379 psWarpOptions->hSrcDS = hSrcDS;
380 psWarpOptions->hDstDS = hDstDS;
382 psWarpOptions->nBandCount = 1;
383 psWarpOptions->panSrcBands =
reinterpret_cast< int *
>( CPLMalloc(
sizeof(
int ) * 1 ) );
384 psWarpOptions->panDstBands =
reinterpret_cast< int *
>( CPLMalloc(
sizeof(
int ) * 1 ) );
385 psWarpOptions->panSrcBands[0] = 1;
386 psWarpOptions->panDstBands[0] = 1;
387 double noDataValue = GDALGetRasterNoDataValue( GDALGetRasterBand( hDstDS, 1 ),
nullptr );
388 psWarpOptions->padfDstNoDataReal =
reinterpret_cast< double *
>( CPLMalloc(
sizeof(
double ) * 1 ) );
389 psWarpOptions->padfDstNoDataReal[0] = noDataValue;
390 psWarpOptions->padfSrcNoDataReal =
reinterpret_cast< double *
>( CPLMalloc(
sizeof(
double ) * 1 ) );
391 psWarpOptions->padfSrcNoDataReal[0] = noDataValue;
392 psWarpOptions->eResampleAlg = resampleAlg;
395 psWarpOptions->pTransformerArg = GDALCreateGenImgProjTransformer2( hSrcDS, hDstDS, papszOptions );
397 if ( ! psWarpOptions->pTransformerArg )
402 psWarpOptions->pfnTransformer = GDALGenImgProjTransform;
403 psWarpOptions->papszWarpOptions = CSLSetNameValue( psWarpOptions-> papszWarpOptions,
"INIT_DEST",
"NO_DATA" );
407 GDALWarpOperation oOperation;
408 CPLErr initResult = oOperation.Initialize( psWarpOptions.get() );
409 if ( initResult != CE_Failure )
410 retVal = oOperation.ChunkAndWarpImage( 0, 0, GDALGetRasterXSize( hDstDS ), GDALGetRasterYSize( hDstDS ) ) == CE_None;
411 GDALDestroyGenImgProjTransformer( psWarpOptions->pTransformerArg );
417 char **papszOptions =
nullptr;
418 if ( pszCoordinateOperation )
419 papszOptions = CSLSetNameValue( papszOptions,
"COORDINATE_OPERATION", pszCoordinateOperation );
421 bool result = resampleSingleBandRasterStatic( hSrcDS, hDstDS, resampleAlg, papszOptions );
422 CSLDestroy( papszOptions );
428 GDALResampleAlg resampleAlg,
432 char **papszOptions =
nullptr;
437 bool result = resampleSingleBandRasterStatic( hSrcDS, hDstDS, resampleAlg, papszOptions );
438 CSLDestroy( papszOptions );
448 GDALRasterIOExtraArg extra;
449 INIT_RASTERIO_EXTRA_ARG( extra );
450 extra.eResampleAlg = resampleAlg;
452 QImage res( outputSize, image.format() );
456 GByte *rgb =
reinterpret_cast<GByte *
>( res.bits() );
458 CPLErr err = GDALRasterIOEx( GDALGetRasterBand( srcDS.get(), 1 ), GF_Read, 0, 0, image.width(), image.height(), rgb + 2, outputSize.width(),
459 outputSize.height(), GDT_Byte,
sizeof( QRgb ), res.bytesPerLine(), &extra );
460 if ( err != CE_None )
462 QgsDebugError( QStringLiteral(
"failed to read red band" ) );
466 err = GDALRasterIOEx( GDALGetRasterBand( srcDS.get(), 2 ), GF_Read, 0, 0, image.width(), image.height(), rgb + 1, outputSize.width(),
467 outputSize.height(), GDT_Byte,
sizeof( QRgb ), res.bytesPerLine(), &extra );
468 if ( err != CE_None )
470 QgsDebugError( QStringLiteral(
"failed to read green band" ) );
474 err = GDALRasterIOEx( GDALGetRasterBand( srcDS.get(), 3 ), GF_Read, 0, 0, image.width(), image.height(), rgb, outputSize.width(),
475 outputSize.height(), GDT_Byte,
sizeof( QRgb ), res.bytesPerLine(), &extra );
476 if ( err != CE_None )
478 QgsDebugError( QStringLiteral(
"failed to read blue band" ) );
482 err = GDALRasterIOEx( GDALGetRasterBand( srcDS.get(), 4 ), GF_Read, 0, 0, image.width(), image.height(), rgb + 3, outputSize.width(),
483 outputSize.height(), GDT_Byte,
sizeof( QRgb ), res.bytesPerLine(), &extra );
484 if ( err != CE_None )
486 QgsDebugError( QStringLiteral(
"failed to read alpha band" ) );
496 GDALDriverH myGdalDriver = GDALGetDriverByName( format.toLocal8Bit().constData() );
500 char **GDALmetadata = GDALGetMetadata( myGdalDriver,
nullptr );
501 message += QLatin1String(
"Format Details:\n" );
502 message += QStringLiteral(
" Extension: %1\n" ).arg( CSLFetchNameValue( GDALmetadata, GDAL_DMD_EXTENSION ) );
503 message += QStringLiteral(
" Short Name: %1" ).arg( GDALGetDriverShortName( myGdalDriver ) );
504 message += QStringLiteral(
" / Long Name: %1\n" ).arg( GDALGetDriverLongName( myGdalDriver ) );
506 if ( !helpUrl.isEmpty() )
507 message += QStringLiteral(
" Help page: %1\n\n" ).arg( helpUrl );
511 CPLXMLNode *psCOL = CPLParseXMLString( GDALGetMetadataItem( myGdalDriver,
512 GDAL_DMD_CREATIONOPTIONLIST,
"" ) );
513 char *pszFormattedXML = CPLSerializeXMLTree( psCOL );
514 if ( pszFormattedXML )
515 message += QString( pszFormattedXML );
517 CPLDestroyXMLNode( psCOL );
518 if ( pszFormattedXML )
519 CPLFree( pszFormattedXML );
526 char **papszRetList =
nullptr;
527 const auto constList = list;
528 for (
const QString &elem : constList )
530 papszRetList = CSLAddString( papszRetList, elem.toLocal8Bit().constData() );
537 GDALDriverH myGdalDriver = GDALGetDriverByName( format.toLocal8Bit().constData() );
538 if ( ! myGdalDriver )
539 return QStringLiteral(
"invalid GDAL driver" );
543 const int ok = GDALValidateCreationOptions( myGdalDriver, papszOptions );
544 CSLDestroy( papszOptions );
547 return QStringLiteral(
"Failed GDALValidateCreationOptions() test" );
551static void setRPCTransformerOptions(
GDALDatasetH hSrcDS,
char ***opts )
553 if ( GDALGetMetadata( hSrcDS,
"RPC" ) )
557 const char *heightStr = GDALGetMetadataItem( hSrcDS,
"HEIGHT_DEFAULT",
"RPC" );
562 heightStr = GDALGetMetadataItem( hSrcDS,
"HEIGHT_OFF",
"RPC" );
565 *opts = CSLAddNameValue( *opts,
"RPC_HEIGHT", heightStr );
571 const char *pszSrcWKT,
572 const char *pszDstWKT,
573 GDALResampleAlg eResampleAlg,
575 const GDALWarpOptions *psOptionsIn )
577 char **opts =
nullptr;
578 setRPCTransformerOptions( hSrcDS, &opts );
579 GDALDatasetH hRetDS = GDALAutoCreateWarpedVRTEx( hSrcDS, pszSrcWKT, pszDstWKT, eResampleAlg, dfMaxError, psOptionsIn, opts );
586 char **opts = CSLDuplicate( papszOptions );
587 setRPCTransformerOptions( hSrcDS, &opts );
588 void *transformer = GDALCreateGenImgProjTransformer2( hSrcDS, hDstDS, opts );
598 return GDALDataType::GDT_Unknown;
601 return GDALDataType::GDT_Byte;
604#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,7,0)
605 return GDALDataType::GDT_Int8;
607 return GDALDataType::GDT_Unknown;
611 return GDALDataType::GDT_UInt16;
614 return GDALDataType::GDT_Int16;
617 return GDALDataType::GDT_UInt32;
620 return GDALDataType::GDT_Int32;
623 return GDALDataType::GDT_Float32;
626 return GDALDataType::GDT_Float64;
629 return GDALDataType::GDT_CInt16;
632 return GDALDataType::GDT_CInt32;
635 return GDALDataType::GDT_CFloat32;
638 return GDALDataType::GDT_CFloat64;
642 return GDALDataType::GDT_Unknown;
646 return GDALDataType::GDT_Unknown;
651 GDALResampleAlg eResampleAlg = GRA_NearestNeighbour;
656 eResampleAlg = GRA_NearestNeighbour;
660 eResampleAlg = GRA_Bilinear;
664 eResampleAlg = GRA_Cubic;
668 eResampleAlg = GRA_CubicSpline;
672 eResampleAlg = GRA_Lanczos;
676 eResampleAlg = GRA_Average;
680 eResampleAlg = GRA_Mode;
687#ifndef QT_NO_NETWORKPROXY
697 if ( settings.
value( QStringLiteral(
"proxy/proxyEnabled" ),
false ).toBool() )
701 if ( ! proxies.isEmpty() )
703 const QNetworkProxy proxy( proxies.first() );
708 const QString proxyHost( proxy.hostName() );
709 const quint16 proxyPort( proxy.port() );
711 const QString proxyUser( proxy.user() );
712 const QString proxyPassword( proxy.password() );
714 if ( ! proxyHost.isEmpty() )
716 QString connection( proxyHost );
719 connection +=
':' + QString::number( proxyPort );
721 CPLSetConfigOption(
"GDAL_HTTP_PROXY", connection.toUtf8() );
722 if ( ! proxyUser.isEmpty( ) )
724 QString credentials( proxyUser );
725 if ( ! proxyPassword.isEmpty( ) )
727 credentials +=
':' + proxyPassword;
729 CPLSetConfigOption(
"GDAL_HTTP_PROXYUSERPWD", credentials.toUtf8() );
738 const QFileInfo info( path );
739 const long long size = info.size();
745 const QString suffix = info.suffix().toLower();
746 static const QStringList sFileSizeDependentExtensions
748 QStringLiteral(
"xlsx" ),
749 QStringLiteral(
"ods" ),
750 QStringLiteral(
"csv" )
752 if ( sFileSizeDependentExtensions.contains( suffix ) )
755 return size < smallFileSizeLimit;
765#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,4,0)
767 static std::once_flag initialized;
768 static QStringList SUPPORTED_DB_LAYERS_EXTENSIONS;
769 std::call_once( initialized, []
773 GDALDriverH driver =
nullptr;
775 QSet< QString > extensions;
777 for (
int i = 0; i < GDALGetDriverCount(); ++i )
779 driver = GDALGetDriver( i );
786 bool isMultiLayer =
false;
787 if ( QString( GDALGetMetadataItem( driver, GDAL_DCAP_RASTER,
nullptr ) ) == QLatin1String(
"YES" ) )
789 if ( GDALGetMetadataItem( driver, GDAL_DMD_SUBDATASETS,
nullptr ) )
794 if ( !isMultiLayer && QString( GDALGetMetadataItem( driver, GDAL_DCAP_VECTOR,
nullptr ) ) == QLatin1String(
"YES" ) )
796 if ( GDALGetMetadataItem( driver, GDAL_DCAP_MULTIPLE_VECTOR_LAYERS,
nullptr ) )
805 const QString driverExtensions = GDALGetMetadataItem( driver, GDAL_DMD_EXTENSIONS,
"" );
806 if ( driverExtensions.isEmpty() )
809 const QStringList splitExtensions = driverExtensions.split(
' ', Qt::SkipEmptyParts );
811 for (
const QString &ext : splitExtensions )
814 if ( ext == QLatin1String(
"tif" ) || ext == QLatin1String(
"tiff" ) )
817 extensions.insert( ext );
821 SUPPORTED_DB_LAYERS_EXTENSIONS = QStringList( extensions.constBegin(), extensions.constEnd() );
823 return SUPPORTED_DB_LAYERS_EXTENSIONS;
826 static const QStringList SUPPORTED_DB_LAYERS_EXTENSIONS
828 QStringLiteral(
"gpkg" ),
829 QStringLiteral(
"sqlite" ),
830 QStringLiteral(
"db" ),
831 QStringLiteral(
"gdb" ),
832 QStringLiteral(
"kml" ),
833 QStringLiteral(
"kmz" ),
834 QStringLiteral(
"osm" ),
835 QStringLiteral(
"mdb" ),
836 QStringLiteral(
"accdb" ),
837 QStringLiteral(
"xls" ),
838 QStringLiteral(
"xlsx" ),
839 QStringLiteral(
"ods" ),
840 QStringLiteral(
"gpx" ),
841 QStringLiteral(
"pdf" ),
842 QStringLiteral(
"pbf" ),
843 QStringLiteral(
"vrt" ),
844 QStringLiteral(
"nc" ),
845 QStringLiteral(
"dxf" ),
846 QStringLiteral(
"shp.zip" ),
847 QStringLiteral(
"gdb.zip" ) };
848 return SUPPORTED_DB_LAYERS_EXTENSIONS;
856 const thread_local QRegularExpression vsiRx( QStringLiteral(
"^(/vsi.+?/)" ), QRegularExpression::PatternOption::CaseInsensitiveOption );
857 const QRegularExpressionMatch vsiMatch = vsiRx.match( path );
858 if ( vsiMatch.hasMatch() )
859 return vsiMatch.captured( 1 );
861 if ( path.endsWith( QLatin1String(
".shp.zip" ), Qt::CaseInsensitive ) ||
862 path.endsWith( QLatin1String(
".gdb.zip" ), Qt::CaseInsensitive ) )
865 if ( GDALIdentifyDriverEx( path.toUtf8().constData(), GDAL_OF_VECTOR,
nullptr,
nullptr ) )
867 return QStringLiteral(
"/vsizip/" );
869 else if ( path.endsWith( QLatin1String(
".zip" ), Qt::CaseInsensitive ) )
872 const char *
const apszAllowedDrivers[] = {
"GTFS",
nullptr };
873 if ( GDALIdentifyDriverEx( path.toUtf8().constData(), GDAL_OF_VECTOR, apszAllowedDrivers,
nullptr ) )
875 return QStringLiteral(
"/vsizip/" );
877 else if ( path.endsWith( QLatin1String(
".tar" ), Qt::CaseInsensitive ) ||
878 path.endsWith( QLatin1String(
".tar.gz" ), Qt::CaseInsensitive ) ||
879 path.endsWith( QLatin1String(
".tgz" ), Qt::CaseInsensitive ) )
880 return QStringLiteral(
"/vsitar/" );
881 else if ( path.endsWith( QLatin1String(
".gz" ), Qt::CaseInsensitive ) )
882 return QStringLiteral(
"/vsigzip/" );
883#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,7,0)
884 else if ( vsiPrefixes.contains( QStringLiteral(
"/vsi7z/" ) ) &&
885 ( path.endsWith( QLatin1String(
".7z" ), Qt::CaseInsensitive ) ||
886 path.endsWith( QLatin1String(
".lpk" ), Qt::CaseInsensitive ) ||
887 path.endsWith( QLatin1String(
".lpkx" ), Qt::CaseInsensitive ) ||
888 path.endsWith( QLatin1String(
".mpk" ), Qt::CaseInsensitive ) ||
889 path.endsWith( QLatin1String(
".mpkx" ), Qt::CaseInsensitive ) ) )
890 return QStringLiteral(
"/vsi7z/" );
891 else if ( vsiPrefixes.contains( QStringLiteral(
"/vsirar/" ) ) &&
892 path.endsWith( QLatin1String(
".rar" ), Qt::CaseInsensitive ) )
893 return QStringLiteral(
"/vsirar/" );
901 QStringList res { QStringLiteral(
"/vsizip/" ),
902 QStringLiteral(
"/vsitar/" ),
903 QStringLiteral(
"/vsigzip/" ),
905#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,7,0)
906 res.append( QStringLiteral(
"/vsi7z/" ) );
907 res.append( QStringLiteral(
"/vsirar/" ) );
915 static std::once_flag initialized;
916 static QList<QgsGdalUtils::VsiNetworkFileSystemDetails> VSI_FILE_SYSTEM_DETAILS;
917 std::call_once( initialized, []
919 if (
char **papszPrefixes = VSIGetFileSystemsPrefixes() )
921 for (
int i = 0; papszPrefixes[i]; i++ )
924 details.
identifier = QString( papszPrefixes[i] );
930 if ( details.
identifier == QLatin1String(
"vsicurl" ) )
931 details.
name = QObject::tr(
"HTTP/HTTPS/FTP" );
932 else if ( details.
identifier == QLatin1String(
"vsis3" ) )
933 details.
name = QObject::tr(
"AWS S3" );
934 else if ( details.
identifier == QLatin1String(
"vsigs" ) )
935 details.
name = QObject::tr(
"Google Cloud Storage" );
936 else if ( details.
identifier == QLatin1String(
"vsiaz" ) )
937 details.
name = QObject::tr(
"Microsoft Azure Blob" );
938 else if ( details.
identifier == QLatin1String(
"vsiadls" ) )
939 details.
name = QObject::tr(
"Microsoft Azure Data Lake Storage" );
940 else if ( details.
identifier == QLatin1String(
"vsioss" ) )
941 details.
name = QObject::tr(
"Alibaba Cloud OSS" );
942 else if ( details.
identifier == QLatin1String(
"vsiswift" ) )
943 details.
name = QObject::tr(
"OpenStack Swift Object Storage" );
944 else if ( details.
identifier == QLatin1String(
"vsihdfs" ) )
945 details.
name = QObject::tr(
"Hadoop File System" );
948 VSI_FILE_SYSTEM_DETAILS.append( details );
951 CSLDestroy( papszPrefixes );
955 return VSI_FILE_SYSTEM_DETAILS;
961 for (
const QString &archivePrefix : prefixes )
964 if ( prefix.contains( archivePrefix ) )
972 QStringList res { QStringLiteral(
".zip" ),
973 QStringLiteral(
".tar" ),
974 QStringLiteral(
".tar.gz" ),
975 QStringLiteral(
".tgz" ),
976 QStringLiteral(
".gz" ),
978#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,7,0)
979 res.append( { QStringLiteral(
".7z" ),
980 QStringLiteral(
".lpk" ),
981 QStringLiteral(
".lpkx" ),
982 QStringLiteral(
".mpk" ),
983 QStringLiteral(
".mpkx" ),
984 QStringLiteral(
".rar" )
992 const QString extWithDot = extension.startsWith(
'.' ) ? extension : (
'.' + extension );
998 if ( prefix.isEmpty() )
1001 QString vsiPrefix = prefix;
1002 if ( vsiPrefix.startsWith(
'/' ) )
1003 vsiPrefix = vsiPrefix.mid( 1 );
1004 if ( vsiPrefix.endsWith(
'/' ) )
1005 vsiPrefix.chop( 1 );
1007 if ( !vsiPrefix.startsWith( QLatin1String(
"vsi" ) ) )
1010 if ( vsiPrefix == QLatin1String(
"vsizip" ) ||
1011 vsiPrefix == QLatin1String(
"vsigzip" ) ||
1012 vsiPrefix == QLatin1String(
"vsitar" ) ||
1013 vsiPrefix == QLatin1String(
"vsi7z" ) ||
1014 vsiPrefix == QLatin1String(
"vsirar" ) )
1017 else if ( vsiPrefix == QLatin1String(
"vsicurl" ) ||
1018 vsiPrefix == QLatin1String(
"vsicurl_streaming" ) )
1021 else if ( vsiPrefix == QLatin1String(
"vsis3" ) ||
1022 vsiPrefix == QLatin1String(
"vsicurl_streaming" ) ||
1023 vsiPrefix == QLatin1String(
"vsigs" ) ||
1024 vsiPrefix == QLatin1String(
"vsigs_streaming" ) ||
1025 vsiPrefix == QLatin1String(
"vsiaz" ) ||
1026 vsiPrefix == QLatin1String(
"vsiaz_streaming" ) ||
1027 vsiPrefix == QLatin1String(
"vsiadls" ) ||
1028 vsiPrefix == QLatin1String(
"vsioss" ) ||
1029 vsiPrefix == QLatin1String(
"vsioss_streaming" ) ||
1030 vsiPrefix == QLatin1String(
"vsiswift" ) ||
1031 vsiPrefix == QLatin1String(
"vsiswift_streaming" ) ||
1032 vsiPrefix == QLatin1String(
"vsihdfs" ) ||
1033 vsiPrefix == QLatin1String(
"vsiwebhdfs" ) )
1036 else if ( vsiPrefix == QLatin1String(
"vsimem" ) )
1044 CPLPushErrorHandler( CPLQuietErrorHandler );
1046 GDALDriverH hDriver =
nullptr;
1051 hDriver = GDALIdentifyDriverEx( vrtPath.toUtf8().constData(), GDAL_OF_VECTOR,
nullptr,
nullptr );
1055 hDriver = GDALIdentifyDriverEx( vrtPath.toUtf8().constData(), GDAL_OF_RASTER,
nullptr,
nullptr );
1068 CPLPopErrorHandler();
1069 return static_cast< bool >( hDriver );
1076 const QString gdalDriverHelpTopic = GDALGetMetadataItem( hDriver, GDAL_DMD_HELPTOPIC,
nullptr );
1077 if ( !gdalDriverHelpTopic.isEmpty() )
1078 return QStringLiteral(
"https://gdal.org/%1" ).arg( gdalDriverHelpTopic );
1085 QString vsiPrefix = prefix;
1086 if ( !vsiPrefix.startsWith(
'/' ) )
1087 vsiPrefix.prepend(
'/' );
1088 if ( !vsiPrefix.endsWith(
'/' ) )
1089 vsiPrefix.append(
'/' );
1091 QString vsiPath = path;
1092 if ( vsiPath.endsWith(
'/' ) )
1095 const QString bucket = vsiPrefix + vsiPath;
1097 for (
auto it = options.constBegin(); it != options.constEnd(); ++it )
1099#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3, 6, 0)
1100 VSISetPathSpecificOption( bucket.toUtf8().constData(), it.key().toUtf8().constData(), it.value().toString().toUtf8().constData() );
1101#elif GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3, 5, 0)
1102 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).
RasterResamplingMethod
Resampling method for raster 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.
@ 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.
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 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 GDALResampleAlg gdalResamplingAlgorithm(Qgis::RasterResamplingMethod method)
Returns the GDAL resampling method corresponding to the QGIS resampling method.
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 QString gdalDocumentationUrlForDriver(GDALDriverH hDriver)
Returns the URL for the GDAL documentation for the specified driver.
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 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 QString validateCreationOptionsFormat(const QStringList &creationOptions, 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 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, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE())
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.
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.
A rectangle specified with double values.
Stores settings for use within QGIS.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
std::unique_ptr< GDALWarpOptions, GDALWarpOptionsDeleter > warp_options_unique_ptr
Scoped GDAL warp options.
std::unique_ptr< std::remove_pointer< GDALDatasetH >::type, GDALDatasetCloser > dataset_unique_ptr
Scoped GDAL dataset.
#define QgsDebugError(str)
Encapsulates details for a GDAL VSI network file system.
QString name
Translated, user-friendly name.
QString identifier
VSI handler identifier, eg "vsis3".