21 #define CPL_SUPRESS_CPLUSPLUS //#spellok
23 #include "gdalwarper.h"
24 #include "cpl_string.h"
26 #include <QNetworkProxy>
32 QString driverShortName = GDALGetDriverShortName( driver );
33 if ( driverShortName == QLatin1String(
"SQLite" ) )
38 char **driverMetadata = GDALGetMetadata( driver,
nullptr );
39 return CSLFetchBoolean( driverMetadata, GDAL_DCAP_CREATE,
false ) &&
40 CSLFetchBoolean( driverMetadata, GDAL_DCAP_RASTER,
false );
50 GDALDriverH hDriverMem = GDALGetDriverByName(
"MEM" );
58 double cellSizeX = extent.
width() / width;
59 double cellSizeY = extent.
height() / height;
60 double geoTransform[6];
62 geoTransform[1] = cellSizeX;
64 geoTransform[3] = extent.
yMinimum() + ( cellSizeY * height );
66 geoTransform[5] = -cellSizeY;
69 GDALSetGeoTransform( hSrcDS.get(), geoTransform );
75 double cellSizeX = extent.
width() / width;
76 double cellSizeY = extent.
height() / height;
77 double geoTransform[6];
79 geoTransform[1] = cellSizeX;
81 geoTransform[3] = extent.
yMinimum() + ( cellSizeY * height );
83 geoTransform[5] = -cellSizeY;
85 GDALDriverH hDriver = GDALGetDriverByName(
"GTiff" );
92 gdal::dataset_unique_ptr hDstDS( GDALCreate( hDriver, filename.toLocal8Bit().constData(), width, height, 1, dataType,
nullptr ) );
100 GDALSetGeoTransform( hDstDS.get(), geoTransform );
106 if ( image.isNull() )
109 const QRgb *rgb =
reinterpret_cast<const QRgb *
>( image.constBits() );
110 GDALDriverH hDriverMem = GDALGetDriverByName(
"MEM" );
115 gdal::dataset_unique_ptr hSrcDS( GDALCreate( hDriverMem,
"", image.width(), image.height(), 0, GDT_Byte,
nullptr ) );
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 );
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 );
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 );
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 );
151 psWarpOptions->hSrcDS = hSrcDS;
152 psWarpOptions->hDstDS = hDstDS;
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;
160 psWarpOptions->eResampleAlg = resampleAlg;
163 psWarpOptions->pTransformerArg =
164 GDALCreateGenImgProjTransformer( hSrcDS, GDALGetProjectionRef( hSrcDS ),
165 hDstDS, GDALGetProjectionRef( hDstDS ),
167 psWarpOptions->pfnTransformer = GDALGenImgProjTransform;
170 GDALWarpOperation oOperation;
171 oOperation.Initialize( psWarpOptions.get() );
173 oOperation.ChunkAndWarpImage( 0, 0, GDALGetRasterXSize( hDstDS ), GDALGetRasterYSize( hDstDS ) );
175 GDALDestroyGenImgProjTransformer( psWarpOptions->pTransformerArg );
184 GDALRasterIOExtraArg extra;
185 INIT_RASTERIO_EXTRA_ARG( extra );
186 extra.eResampleAlg = resampleAlg;
188 QImage res( outputSize, image.format() );
192 GByte *rgb =
reinterpret_cast<GByte *
>( res.bits() );
194 CPLErr err = GDALRasterIOEx( GDALGetRasterBand( srcDS.get(), 1 ), GF_Read, 0, 0, image.width(), image.height(), rgb + 2, outputSize.width(),
195 outputSize.height(), GDT_Byte,
sizeof( QRgb ), res.bytesPerLine(), &extra );
196 if ( err != CE_None )
198 QgsDebugMsg( QStringLiteral(
"failed to read red band" ) );
202 err = GDALRasterIOEx( GDALGetRasterBand( srcDS.get(), 2 ), GF_Read, 0, 0, image.width(), image.height(), rgb + 1, outputSize.width(),
203 outputSize.height(), GDT_Byte,
sizeof( QRgb ), res.bytesPerLine(), &extra );
204 if ( err != CE_None )
206 QgsDebugMsg( QStringLiteral(
"failed to read green band" ) );
210 err = GDALRasterIOEx( GDALGetRasterBand( srcDS.get(), 3 ), GF_Read, 0, 0, image.width(), image.height(), rgb, outputSize.width(),
211 outputSize.height(), GDT_Byte,
sizeof( QRgb ), res.bytesPerLine(), &extra );
212 if ( err != CE_None )
214 QgsDebugMsg( QStringLiteral(
"failed to read blue band" ) );
218 err = GDALRasterIOEx( GDALGetRasterBand( srcDS.get(), 4 ), GF_Read, 0, 0, image.width(), image.height(), rgb + 3, outputSize.width(),
219 outputSize.height(), GDT_Byte,
sizeof( QRgb ), res.bytesPerLine(), &extra );
220 if ( err != CE_None )
222 QgsDebugMsg( QStringLiteral(
"failed to read alpha band" ) );
232 GDALDriverH myGdalDriver = GDALGetDriverByName( format.toLocal8Bit().constData() );
236 char **GDALmetadata = GDALGetMetadata( myGdalDriver,
nullptr );
237 message += QLatin1String(
"Format Details:\n" );
238 message += QStringLiteral(
" Extension: %1\n" ).arg( CSLFetchNameValue( GDALmetadata, GDAL_DMD_EXTENSION ) );
239 message += QStringLiteral(
" Short Name: %1" ).arg( GDALGetDriverShortName( myGdalDriver ) );
240 message += QStringLiteral(
" / Long Name: %1\n" ).arg( GDALGetDriverLongName( myGdalDriver ) );
241 message += QStringLiteral(
" Help page: http://www.gdal.org/%1\n\n" ).arg( CSLFetchNameValue( GDALmetadata, GDAL_DMD_HELPTOPIC ) );
245 CPLXMLNode *psCOL = CPLParseXMLString( GDALGetMetadataItem( myGdalDriver,
246 GDAL_DMD_CREATIONOPTIONLIST,
"" ) );
247 char *pszFormattedXML = CPLSerializeXMLTree( psCOL );
248 if ( pszFormattedXML )
249 message += QString( pszFormattedXML );
251 CPLDestroyXMLNode( psCOL );
252 if ( pszFormattedXML )
253 CPLFree( pszFormattedXML );
260 char **papszRetList =
nullptr;
261 const auto constList = list;
262 for (
const QString &elem : constList )
264 papszRetList = CSLAddString( papszRetList, elem.toLocal8Bit().constData() );
271 GDALDriverH myGdalDriver = GDALGetDriverByName( format.toLocal8Bit().constData() );
272 if ( ! myGdalDriver )
273 return QStringLiteral(
"invalid GDAL driver" );
277 int ok = GDALValidateCreationOptions( myGdalDriver, papszOptions );
278 CSLDestroy( papszOptions );
281 return QStringLiteral(
"Failed GDALValidateCreationOptions() test" );
285 #if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(2,3,0)
289 static void GDALWarpInitDefaultBandMapping( GDALWarpOptions *psOptionsIn,
int nBandCount )
291 if ( psOptionsIn->nBandCount != 0 ) {
return; }
293 psOptionsIn->nBandCount = nBandCount;
295 psOptionsIn->panSrcBands =
static_cast<int *
>(
296 CPLMalloc(
sizeof(
int ) * psOptionsIn->nBandCount ) );
297 psOptionsIn->panDstBands =
static_cast<int *
>(
298 CPLMalloc(
sizeof(
int ) * psOptionsIn->nBandCount ) );
300 for (
int i = 0; i < psOptionsIn->nBandCount; i++ )
302 psOptionsIn->panSrcBands[i] = i + 1;
303 psOptionsIn->panDstBands[i] = i + 1;
307 static void InitNoData(
int nBandCount,
double **ppdNoDataReal,
double dDataReal )
309 if ( nBandCount <= 0 ) {
return; }
310 if ( *ppdNoDataReal !=
nullptr ) {
return; }
312 *ppdNoDataReal =
static_cast<double *
>(
313 CPLMalloc(
sizeof(
double ) * nBandCount ) );
315 for (
int i = 0; i < nBandCount; ++i )
317 ( *ppdNoDataReal )[i] = dDataReal;
321 static void GDALWarpInitNoDataReal( GDALWarpOptions *psOptionsIn,
double dNoDataReal )
323 InitNoData( psOptionsIn->nBandCount, &psOptionsIn->padfDstNoDataReal, dNoDataReal );
324 InitNoData( psOptionsIn->nBandCount, &psOptionsIn->padfSrcNoDataReal, dNoDataReal );
326 InitNoData( psOptionsIn->nBandCount, &psOptionsIn->padfDstNoDataImag, 0 );
327 InitNoData( psOptionsIn->nBandCount, &psOptionsIn->padfSrcNoDataImag, 0 );
331 #if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,2,0)
333 GDALDatasetH GDALAutoCreateWarpedVRTEx(
GDALDatasetH hSrcDS,
const char *pszSrcWKT,
const char *pszDstWKT, GDALResampleAlg eResampleAlg,
334 double dfMaxError,
const GDALWarpOptions *psOptionsIn,
char **papszTransformerOptions )
336 VALIDATE_POINTER1( hSrcDS,
"GDALAutoCreateWarpedVRT",
nullptr );
341 GDALWarpOptions *psWO =
nullptr;
342 if ( psOptionsIn !=
nullptr )
343 psWO = GDALCloneWarpOptions( psOptionsIn );
345 psWO = GDALCreateWarpOptions();
347 psWO->eResampleAlg = eResampleAlg;
349 psWO->hSrcDS = hSrcDS;
351 GDALWarpInitDefaultBandMapping( psWO, GDALGetRasterCount( hSrcDS ) );
356 for (
int i = 0; i < psWO->nBandCount; i++ )
358 GDALRasterBandH rasterBand = GDALGetRasterBand( psWO->hSrcDS, psWO->panSrcBands[i] );
361 double noDataValue = GDALGetRasterNoDataValue( rasterBand, &hasNoDataValue );
363 if ( hasNoDataValue )
366 int bClamped = FALSE;
367 int bRounded = FALSE;
369 GDALAdjustValueToDataType( GDALGetRasterDataType( rasterBand ),
370 noDataValue, &bClamped, &bRounded ) );
373 GDALWarpInitNoDataReal( psWO, -1e10 );
375 psWO->padfSrcNoDataReal[i] = noDataValue;
376 psWO->padfDstNoDataReal[i] = noDataValue;
381 if ( psWO->padfDstNoDataReal !=
nullptr )
383 if ( CSLFetchNameValue( psWO->papszWarpOptions,
"INIT_DEST" ) ==
nullptr )
385 psWO->papszWarpOptions =
386 CSLSetNameValue( psWO->papszWarpOptions,
"INIT_DEST",
"NO_DATA" );
393 psWO->pfnTransformer = GDALGenImgProjTransform;
395 char **papszOptions =
nullptr;
396 if ( pszSrcWKT !=
nullptr )
397 papszOptions = CSLSetNameValue( papszOptions,
"SRC_SRS", pszSrcWKT );
398 if ( pszDstWKT !=
nullptr )
399 papszOptions = CSLSetNameValue( papszOptions,
"DST_SRS", pszDstWKT );
400 papszOptions = CSLMerge( papszOptions, papszTransformerOptions );
401 psWO->pTransformerArg =
402 GDALCreateGenImgProjTransformer2( psWO->hSrcDS,
nullptr,
404 CSLDestroy( papszOptions );
406 if ( psWO->pTransformerArg ==
nullptr )
408 GDALDestroyWarpOptions( psWO );
415 double adfDstGeoTransform[6] = { 0.0 };
419 GDALSuggestedWarpOutput( hSrcDS, psWO->pfnTransformer,
420 psWO->pTransformerArg,
421 adfDstGeoTransform, &nDstPixels, &nDstLines );
422 if ( eErr != CE_None )
424 GDALDestroyTransformer( psWO->pTransformerArg );
425 GDALDestroyWarpOptions( psWO );
434 GDALSetGenImgProjTransformerDstGeoTransform(
435 psWO->pTransformerArg, adfDstGeoTransform );
440 if ( dfMaxError > 0.0 )
442 psWO->pTransformerArg =
443 GDALCreateApproxTransformer( psWO->pfnTransformer,
444 psWO->pTransformerArg,
446 psWO->pfnTransformer = GDALApproxTransform;
447 GDALApproxTransformerOwnsSubtransformer( psWO->pTransformerArg, TRUE );
454 = GDALCreateWarpedVRT( hSrcDS, nDstPixels, nDstLines,
455 adfDstGeoTransform, psWO );
457 GDALDestroyWarpOptions( psWO );
459 if ( pszDstWKT !=
nullptr )
460 GDALSetProjection( hDstDS, pszDstWKT );
461 else if ( pszSrcWKT !=
nullptr )
462 GDALSetProjection( hDstDS, pszSrcWKT );
463 else if ( GDALGetGCPCount( hSrcDS ) > 0 )
464 GDALSetProjection( hDstDS, GDALGetGCPProjection( hSrcDS ) );
466 GDALSetProjection( hDstDS, GDALGetProjectionRef( hSrcDS ) );
475 const char *pszSrcWKT,
476 const char *pszDstWKT,
477 GDALResampleAlg eResampleAlg,
479 const GDALWarpOptions *psOptionsIn )
481 char **opts =
nullptr;
482 if ( GDALGetMetadata( hSrcDS,
"RPC" ) )
485 const char *heightOffStr = GDALGetMetadataItem( hSrcDS,
"HEIGHT_OFF",
"RPC" );
487 opts = CSLAddNameValue( opts,
"RPC_HEIGHT", heightOffStr );
490 return GDALAutoCreateWarpedVRTEx( hSrcDS, pszSrcWKT, pszDstWKT, eResampleAlg, dfMaxError, psOptionsIn, opts );
495 char **opts = CSLDuplicate( papszOptions );
496 if ( GDALGetMetadata( hSrcDS,
"RPC" ) )
499 const char *heightOffStr = GDALGetMetadataItem( hSrcDS,
"HEIGHT_OFF",
"RPC" );
501 opts = CSLAddNameValue( opts,
"RPC_HEIGHT", heightOffStr );
503 void *transformer = GDALCreateGenImgProjTransformer2( hSrcDS, hDstDS, opts );
508 #ifndef QT_NO_NETWORKPROXY
518 if ( settings.
value( QStringLiteral(
"proxy/proxyEnabled" ),
false ).toBool() )
522 if ( ! proxies.isEmpty() )
524 QNetworkProxy proxy( proxies.first() );
529 QString proxyHost( proxy.hostName() );
530 qint16 proxyPort( proxy.port() );
532 QString proxyUser( proxy.user() );
533 QString proxyPassword( proxy.password() );
535 if ( ! proxyHost.isEmpty() )
537 QString connection( proxyHost );
540 connection +=
':' + QString::number( proxyPort );
542 CPLSetConfigOption(
"GDAL_HTTP_PROXY", connection.toUtf8() );
543 if ( ! proxyUser.isEmpty( ) )
545 QString credentials( proxyUser );
546 if ( ! proxyPassword.isEmpty( ) )
548 credentials +=
':' + proxyPassword;
550 CPLSetConfigOption(
"GDAL_HTTP_PROXYUSERPWD", credentials.toUtf8() );