29 #include <QCoreApplication>
30 #include <QProgressDialog>
31 #include <QTextStream>
32 #include <QMessageBox>
37 #include <cpl_string.h>
46 double geoTransform[6];
47 globalOutputParameters( extent, width, height, geoTransform, pixelSize );
49 return initOutput( width, height,
crs, geoTransform, 1, dataType, QList<bool>(), QList<double>() );
58 double geoTransform[6];
59 globalOutputParameters( extent, width, height, geoTransform, pixelSize );
61 return initOutput( width, height,
crs, geoTransform, nBands, dataType, QList<bool>(), QList<double>() );
65 : mOutputUrl( outputUrl )
70 QgsRasterFileWriter::QgsRasterFileWriter()
112 QgsDebugMsgLevel( QStringLiteral(
"reading from %1" ).arg(
typeid( *iface ).name() ), 4 );
116 QgsDebugMsg( QStringLiteral(
"iface->srcInput() == 0" ) );
121 QgsDebugMsgLevel( QStringLiteral(
"srcInput = %1" ).arg(
typeid( srcInput ).name() ), 4 );
124 mFeedback = feedback;
131 QFileInfo fileInfo( mOutputUrl );
132 if ( !fileInfo.exists() )
134 QDir dir = fileInfo.dir();
135 if ( !dir.mkdir( fileInfo.fileName() ) )
137 QgsDebugMsg(
"Cannot create output VRT directory " + fileInfo.fileName() +
" in " + dir.absolutePath() );
144 QFile pyramidFile( mOutputUrl + ( mTiledMode ?
".vrt.ovr" :
".ovr" ) );
145 if ( pyramidFile.exists() )
146 pyramidFile.remove();
147 pyramidFile.setFileName( mOutputUrl + ( mTiledMode ?
".vrt.rrd" :
".rrd" ) );
148 if ( pyramidFile.exists() )
149 pyramidFile.remove();
151 if ( mMode ==
Image )
153 WriterError e = writeImageRaster( &iter, nCols, nRows, outputExtent,
crs, feedback );
158 WriterError e = writeDataRaster( pipe, &iter, nCols, nRows, outputExtent,
crs, transformContext, feedback );
181 QgsDebugMsg( QStringLiteral(
"Cannot get source data provider" ) );
198 for (
int i = 2; i <= nBands; ++i )
210 QList<bool> destHasNoDataValueList;
211 QList<double> destNoDataValueList;
212 QList<Qgis::DataType> destDataTypeList;
213 destDataTypeList.reserve( nBands );
214 destHasNoDataValueList.reserve( nBands );
215 destNoDataValueList.reserve( nBands );
217 const bool isGpkgOutput = mOutputProviderKey ==
"gdal" &&
218 mOutputFormat.compare( QLatin1String(
"gpkg" ), Qt::CaseInsensitive ) == 0;
220 double geoTransform[6];
221 globalOutputParameters( outputExtent, nCols, nRows, geoTransform, pixelSize );
222 const auto srcProviderExtent( srcProvider->
extent() );
224 for (
int bandNo = 1; bandNo <= nBands; bandNo++ )
229 bool destHasNoDataValue =
false;
230 double destNoDataValue = std::numeric_limits<double>::quiet_NaN();
235 if ( srcHasNoDataValue )
240 destHasNoDataValue =
true;
242 else if ( nuller && !nuller->
noData( bandNo ).isEmpty() )
245 destNoDataValue = nuller->
noData( bandNo ).value( 0 ).min();
246 destHasNoDataValue =
true;
251 else if ( !( isGpkgOutput && destDataType ==
Qgis::Byte ) )
259 outputExtentInSrcCrs = ct.transformBoundingBox( outputExtent );
261 if ( !srcProviderExtent.contains( outputExtentInSrcCrs ) &&
262 ( std::fabs( srcProviderExtent.xMinimum() - outputExtentInSrcCrs.
xMinimum() ) > geoTransform[1] / 2 ||
263 std::fabs( srcProviderExtent.xMaximum() - outputExtentInSrcCrs.
xMaximum() ) > geoTransform[1] / 2 ||
264 std::fabs( srcProviderExtent.yMinimum() - outputExtentInSrcCrs.
yMinimum() ) > std::fabs( geoTransform[5] ) / 2 ||
265 std::fabs( srcProviderExtent.yMaximum() - outputExtentInSrcCrs.
yMaximum() ) > std::fabs( geoTransform[5] ) / 2 ) )
276 destNoDataValue = typeMinValue;
280 destNoDataValue = typeMaxValue;
287 destHasNoDataValue =
true;
291 if ( nuller && destHasNoDataValue )
296 QgsDebugMsgLevel( QStringLiteral(
"bandNo = %1 destDataType = %2 destHasNoDataValue = %3 destNoDataValue = %4" ).arg( bandNo ).arg( destDataType ).arg( destHasNoDataValue ).arg( destNoDataValue ), 4 );
297 destDataTypeList.append( destDataType );
298 destHasNoDataValueList.append( destHasNoDataValue );
299 destNoDataValueList.append( destNoDataValue );
304 for (
int i = 1; i < nBands; i++ )
306 if ( destDataTypeList.value( i ) > destDataType )
308 destDataType = destDataTypeList.value( i );
314 for (
int attempt = 0; attempt < 2; attempt ++ )
318 std::unique_ptr<QgsRasterDataProvider> destProvider(
319 initOutput( nCols, nRows,
crs, geoTransform, nBands, destDataType, destHasNoDataValueList, destNoDataValueList ) );
326 if ( !destProvider->isValid() )
328 if ( feedback && !destProvider->error().isEmpty() )
330 feedback->
appendError( destProvider->error().summary() );
334 if ( nCols != destProvider->xSize() || nRows != destProvider->ySize() )
336 QgsDebugMsg( QStringLiteral(
"Created raster does not have requested dimensions" ) );
339 feedback->
appendError( QObject::tr(
"Created raster does not have requested dimensions" ) );
343 if ( nBands != destProvider->bandCount() )
345 QgsDebugMsg( QStringLiteral(
"Created raster does not have requested band count" ) );
348 feedback->
appendError( QObject::tr(
"Created raster does not have requested band count" ) );
356 destDataType = destProvider->dataType( 1 );
360 error = writeDataRaster( pipe, iter, nCols, nRows, outputExtent,
crs, destDataType, destHasNoDataValueList, destNoDataValueList, destProvider.get(), feedback );
367 destProvider->remove();
368 destProvider.reset();
376 for (
int i = 0; i < nBands; i++ )
378 double destNoDataValue;
380 destDataTypeList.replace( i, destDataType );
381 destNoDataValueList.replace( i, destNoDataValue );
383 destDataType = destDataTypeList.value( 0 );
396 static int qgsDivRoundUp(
int a,
int b )
398 return a / b + ( ( ( a % b ) != 0 ) ? 1 : 0 );
403 int nCols,
int nRows,
407 const QList<bool> &destHasNoDataValueList,
408 const QList<double> &destNoDataValueList,
413 Q_UNUSED( destHasNoDataValueList )
427 std::vector< std::unique_ptr<QgsRasterBlock> > blockList;
428 std::vector< std::unique_ptr<QgsRasterBlock> > destBlockList;
430 blockList.resize( nBands );
431 destBlockList.resize( nBands );
433 for (
int i = 1; i <= nBands; ++i )
436 if ( destProvider && destHasNoDataValueList.value( i - 1 ) )
438 destProvider->
setNoDataValue( i, destNoDataValueList.value( i - 1 ) );
448 nParts = nPartsX * nPartsY;
455 for (
int i = 1; i <= nBands; ++i )
463 QString vrtFilePath( mOutputUrl +
'/' + vrtFileName() );
464 writeVRT( vrtFilePath );
467 buildPyramids( vrtFilePath );
474 buildPyramids( mOutputUrl, destProvider );
481 blockList[i - 1].reset( block );
485 if ( feedback && fileIndex < ( nParts - 1 ) )
487 feedback->
setProgress( 100.0 * fileIndex /
static_cast< double >( nParts ) );
495 for (
int i = 1; i <= nBands; ++i )
497 if ( srcProvider && srcProvider->
dataType( i ) == destDataType )
504 blockList[i - 1]->convert( destDataType );
506 destBlockList[i - 1] = std::move( blockList[i - 1] );
511 std::unique_ptr< QgsRasterDataProvider > partDestProvider( createPartProvider( outputExtent,
512 nCols, iterCols, iterRows,
513 iterLeft, iterTop, mOutputUrl,
514 fileIndex, nBands, destDataType,
crs ) );
516 if ( !partDestProvider || !partDestProvider->isValid() )
522 for (
int i = 1; i <= nBands; ++i )
524 if ( destHasNoDataValueList.value( i - 1 ) )
526 partDestProvider->setNoDataValue( i, destNoDataValueList.value( i - 1 ) );
528 if ( destBlockList[ i - 1 ]->isEmpty() )
531 if ( !partDestProvider->write( destBlockList[i - 1]->bits( 0 ), i, iterCols, iterRows, 0, 0 ) )
535 addToVRT( partFileName( fileIndex ), i, iterCols, iterRows, iterLeft, iterTop );
539 else if ( destProvider )
542 for (
int i = 1; i <= nBands; ++i )
544 if ( destBlockList[ i - 1 ]->isEmpty() )
547 if ( !destProvider->
write( destBlockList[i - 1]->bits( 0 ), i, iterCols, iterRows, iterLeft, iterTop ) )
583 const size_t nMaxPixels =
static_cast<size_t>( mMaxTileWidth ) * mMaxTileHeight;
584 std::vector<unsigned char> redData( nMaxPixels );
585 std::vector<unsigned char> greenData( nMaxPixels );
586 std::vector<unsigned char> blueData( nMaxPixels );
587 std::vector<unsigned char> alphaData( nMaxPixels );
588 int iterLeft = 0, iterTop = 0, iterCols = 0, iterRows = 0;
593 double geoTransform[6];
594 globalOutputParameters( outputExtent, nCols, nRows, geoTransform, pixelSize );
596 const int nOutputBands = 4;
597 std::unique_ptr< QgsRasterDataProvider > destProvider( initOutput( nCols, nRows,
crs, geoTransform, nOutputBands,
Qgis::Byte ) );
604 if ( !destProvider->
isValid() )
612 if ( nCols != destProvider->
xSize() || nRows != destProvider->
ySize() )
614 QgsDebugMsg( QStringLiteral(
"Created raster does not have requested dimensions" ) );
617 feedback->
appendError( QObject::tr(
"Created raster does not have requested dimensions" ) );
621 if ( nOutputBands != destProvider->
bandCount() )
623 QgsDebugMsg( QStringLiteral(
"Created raster does not have requested band count" ) );
626 feedback->
appendError( QObject::tr(
"Created raster does not have requested band count" ) );
632 QgsDebugMsg( QStringLiteral(
"Created raster does not have requested data type" ) );
635 feedback->
appendError( QObject::tr(
"Created raster does not have requested data type" ) );
648 nParts = nPartsX * nPartsY;
651 std::unique_ptr< QgsRasterBlock > inputBlock;
652 while ( iter->
readNextRasterPart( 1, iterCols, iterRows, inputBlock, iterLeft, iterTop ) )
654 if ( !inputBlock || inputBlock->isEmpty() )
659 if ( feedback && fileIndex < ( nParts - 1 ) )
661 feedback->
setProgress( 100.0 * fileIndex /
static_cast< double >( nParts ) );
670 for (
qgssize i = 0; i < nPixels; ++i )
672 QRgb
c = inputBlock->color( i );
673 if ( isPremultiplied )
675 c = qUnpremultiply(
c );
677 redData[i] =
static_cast<unsigned char>( qRed(
c ) );
678 greenData[i] =
static_cast<unsigned char>( qGreen(
c ) );
679 blueData[i] =
static_cast<unsigned char>( qBlue(
c ) );
680 alphaData[i] =
static_cast<unsigned char>( qAlpha(
c ) );
686 std::unique_ptr< QgsRasterDataProvider > partDestProvider( createPartProvider( outputExtent,
687 nCols, iterCols, iterRows,
688 iterLeft, iterTop, mOutputUrl, fileIndex,
691 if ( !partDestProvider || partDestProvider->isValid() )
697 if ( !partDestProvider->write( &redData[0], 1, iterCols, iterRows, 0, 0 ) ||
698 !partDestProvider->write( &greenData[0], 2, iterCols, iterRows, 0, 0 ) ||
699 !partDestProvider->write( &blueData[0], 3, iterCols, iterRows, 0, 0 ) ||
700 !partDestProvider->write( &alphaData[0], 4, iterCols, iterRows, 0, 0 ) )
705 addToVRT( partFileName( fileIndex ), 1, iterCols, iterRows, iterLeft, iterTop );
706 addToVRT( partFileName( fileIndex ), 2, iterCols, iterRows, iterLeft, iterTop );
707 addToVRT( partFileName( fileIndex ), 3, iterCols, iterRows, iterLeft, iterTop );
708 addToVRT( partFileName( fileIndex ), 4, iterCols, iterRows, iterLeft, iterTop );
710 else if ( destProvider )
712 if ( !destProvider->
write( &redData[0], 1, iterCols, iterRows, iterLeft, iterTop ) ||
713 !destProvider->
write( &greenData[0], 2, iterCols, iterRows, iterLeft, iterTop ) ||
714 !destProvider->
write( &blueData[0], 3, iterCols, iterRows, iterLeft, iterTop ) ||
715 !destProvider->
write( &alphaData[0], 4, iterCols, iterRows, iterLeft, iterTop ) )
723 destProvider.reset();
732 QString vrtFilePath( mOutputUrl +
'/' + vrtFileName() );
733 writeVRT( vrtFilePath );
736 buildPyramids( vrtFilePath );
743 buildPyramids( mOutputUrl );
749 void QgsRasterFileWriter::addToVRT(
const QString &filename,
int band,
int xSize,
int ySize,
int xOffset,
int yOffset )
751 QDomElement bandElem = mVRTBands.value( band - 1 );
753 QDomElement simpleSourceElem = mVRTDocument.createElement( QStringLiteral(
"SimpleSource" ) );
756 QDomElement sourceFilenameElem = mVRTDocument.createElement( QStringLiteral(
"SourceFilename" ) );
757 sourceFilenameElem.setAttribute( QStringLiteral(
"relativeToVRT" ), QStringLiteral(
"1" ) );
758 QDomText sourceFilenameText = mVRTDocument.createTextNode( filename );
759 sourceFilenameElem.appendChild( sourceFilenameText );
760 simpleSourceElem.appendChild( sourceFilenameElem );
763 QDomElement sourceBandElem = mVRTDocument.createElement( QStringLiteral(
"SourceBand" ) );
764 QDomText sourceBandText = mVRTDocument.createTextNode( QString::number( band ) );
765 sourceBandElem.appendChild( sourceBandText );
766 simpleSourceElem.appendChild( sourceBandElem );
769 QDomElement sourcePropertiesElem = mVRTDocument.createElement( QStringLiteral(
"SourceProperties" ) );
770 sourcePropertiesElem.setAttribute( QStringLiteral(
"RasterXSize" ), xSize );
771 sourcePropertiesElem.setAttribute( QStringLiteral(
"RasterYSize" ), ySize );
772 sourcePropertiesElem.setAttribute( QStringLiteral(
"BlockXSize" ), xSize );
773 sourcePropertiesElem.setAttribute( QStringLiteral(
"BlockYSize" ), ySize );
774 sourcePropertiesElem.setAttribute( QStringLiteral(
"DataType" ), QStringLiteral(
"Byte" ) );
775 simpleSourceElem.appendChild( sourcePropertiesElem );
778 QDomElement srcRectElem = mVRTDocument.createElement( QStringLiteral(
"SrcRect" ) );
779 srcRectElem.setAttribute( QStringLiteral(
"xOff" ), QStringLiteral(
"0" ) );
780 srcRectElem.setAttribute( QStringLiteral(
"yOff" ), QStringLiteral(
"0" ) );
781 srcRectElem.setAttribute( QStringLiteral(
"xSize" ), xSize );
782 srcRectElem.setAttribute( QStringLiteral(
"ySize" ), ySize );
783 simpleSourceElem.appendChild( srcRectElem );
786 QDomElement dstRectElem = mVRTDocument.createElement( QStringLiteral(
"DstRect" ) );
787 dstRectElem.setAttribute( QStringLiteral(
"xOff" ), xOffset );
788 dstRectElem.setAttribute( QStringLiteral(
"yOff" ), yOffset );
789 dstRectElem.setAttribute( QStringLiteral(
"xSize" ), xSize );
790 dstRectElem.setAttribute( QStringLiteral(
"ySize" ), ySize );
791 simpleSourceElem.appendChild( dstRectElem );
793 bandElem.appendChild( simpleSourceElem );
796 void QgsRasterFileWriter::buildPyramids(
const QString &filename,
QgsRasterDataProvider *destProviderIn )
804 destProvider = qobject_cast< QgsRasterDataProvider * >(
QgsProviderRegistry::instance()->createProvider( mOutputProviderKey, filename, providerOptions ) );
805 if ( !destProvider || !destProvider->
isValid() )
815 QList< QgsRasterPyramid> myPyramidList;
816 if ( ! mPyramidsList.isEmpty() )
818 for (
int myCounterInt = 0; myCounterInt < myPyramidList.count(); myCounterInt++ )
820 myPyramidList[myCounterInt].build =
true;
823 QgsDebugMsgLevel( QStringLiteral(
"building pyramids : %1 pyramids, %2 resampling, %3 format, %4 options" ).arg( myPyramidList.count() ).arg( mPyramidsResampling ).arg( mPyramidsFormat ).arg( mPyramidsConfigOptions.count() ), 4 );
825 QString res = destProvider->
buildPyramids( myPyramidList, mPyramidsResampling,
826 mPyramidsFormat, mPyramidsConfigOptions );
832 QString title, message;
833 if ( res == QLatin1String(
"ERROR_WRITE_ACCESS" ) )
835 title = QObject::tr(
"Building Pyramids" );
836 message = QObject::tr(
"Write access denied. Adjust the file permissions and try again." );
838 else if ( res == QLatin1String(
"ERROR_WRITE_FORMAT" ) )
840 title = QObject::tr(
"Building Pyramids" );
841 message = QObject::tr(
"The file was not writable. Some formats do not "
842 "support pyramid overviews. Consult the GDAL documentation if in doubt." );
844 else if ( res == QLatin1String(
"FAILED_NOT_SUPPORTED" ) )
846 title = QObject::tr(
"Building Pyramids" );
847 message = QObject::tr(
"Building pyramid overviews is not supported on this type of raster." );
849 else if ( res == QLatin1String(
"ERROR_VIRTUAL" ) )
851 title = QObject::tr(
"Building Pyramids" );
852 message = QObject::tr(
"Building pyramid overviews is not supported on this type of raster." );
854 QMessageBox::warning(
nullptr, title, message );
857 if ( !destProviderIn )
862 int QgsRasterFileWriter::pyramidsProgress(
double dfComplete,
const char *pszMessage,
void *pData )
864 Q_UNUSED( pszMessage )
865 GDALTermProgress( dfComplete, 0, 0 );
866 QProgressDialog *progressDialog =
static_cast<QProgressDialog *
>( pData );
867 if ( pData && progressDialog->wasCanceled() )
874 progressDialog->setRange( 0, 100 );
875 progressDialog->setValue( dfComplete * 100 );
881 void QgsRasterFileWriter::createVRT(
int xSize,
int ySize,
const QgsCoordinateReferenceSystem &
crs,
double *geoTransform,
Qgis::DataType type,
const QList<bool> &destHasNoDataValueList,
const QList<double> &destNoDataValueList )
883 mVRTDocument.clear();
884 QDomElement VRTDatasetElem = mVRTDocument.createElement( QStringLiteral(
"VRTDataset" ) );
887 VRTDatasetElem.setAttribute( QStringLiteral(
"rasterXSize" ), xSize );
888 VRTDatasetElem.setAttribute( QStringLiteral(
"rasterYSize" ), ySize );
889 mVRTDocument.appendChild( VRTDatasetElem );
892 QDomElement SRSElem = mVRTDocument.createElement( QStringLiteral(
"SRS" ) );
893 QDomText crsText = mVRTDocument.createTextNode(
crs.
toWkt() );
894 SRSElem.appendChild( crsText );
895 VRTDatasetElem.appendChild( SRSElem );
900 QDomElement geoTransformElem = mVRTDocument.createElement( QStringLiteral(
"GeoTransform" ) );
901 QString geoTransformString = QString::number( geoTransform[0],
'f', 6 ) +
", " + QString::number( geoTransform[1] ) +
", " + QString::number( geoTransform[2] ) +
902 ", " + QString::number( geoTransform[3],
'f', 6 ) +
", " + QString::number( geoTransform[4] ) +
", " + QString::number( geoTransform[5] );
903 QDomText geoTransformText = mVRTDocument.createTextNode( geoTransformString );
904 geoTransformElem.appendChild( geoTransformText );
905 VRTDatasetElem.appendChild( geoTransformElem );
918 QStringList colorInterp;
919 colorInterp << QStringLiteral(
"Red" ) << QStringLiteral(
"Green" ) << QStringLiteral(
"Blue" ) << QStringLiteral(
"Alpha" );
921 QMap<Qgis::DataType, QString> dataTypes;
922 dataTypes.insert(
Qgis::Byte, QStringLiteral(
"Byte" ) );
923 dataTypes.insert(
Qgis::UInt16, QStringLiteral(
"UInt16" ) );
924 dataTypes.insert(
Qgis::Int16, QStringLiteral(
"Int16" ) );
925 dataTypes.insert(
Qgis::UInt32, QStringLiteral(
"Int32" ) );
926 dataTypes.insert(
Qgis::Float32, QStringLiteral(
"Float32" ) );
927 dataTypes.insert(
Qgis::Float64, QStringLiteral(
"Float64" ) );
928 dataTypes.insert(
Qgis::CInt16, QStringLiteral(
"CInt16" ) );
929 dataTypes.insert(
Qgis::CInt32, QStringLiteral(
"CInt32" ) );
933 for (
int i = 1; i <= nBands; i++ )
935 QDomElement VRTBand = mVRTDocument.createElement( QStringLiteral(
"VRTRasterBand" ) );
937 VRTBand.setAttribute( QStringLiteral(
"band" ), QString::number( i ) );
938 QString dataType = dataTypes.value( type );
939 VRTBand.setAttribute( QStringLiteral(
"dataType" ), dataType );
941 if ( mMode ==
Image )
943 VRTBand.setAttribute( QStringLiteral(
"dataType" ), QStringLiteral(
"Byte" ) );
944 QDomElement colorInterpElement = mVRTDocument.createElement( QStringLiteral(
"ColorInterp" ) );
945 QDomText interpText = mVRTDocument.createTextNode( colorInterp.value( i - 1 ) );
946 colorInterpElement.appendChild( interpText );
947 VRTBand.appendChild( colorInterpElement );
950 if ( !destHasNoDataValueList.isEmpty() && destHasNoDataValueList.value( i - 1 ) )
952 VRTBand.setAttribute( QStringLiteral(
"NoDataValue" ), QString::number( destNoDataValueList.value( i - 1 ) ) );
955 mVRTBands.append( VRTBand );
956 VRTDatasetElem.appendChild( VRTBand );
960 bool QgsRasterFileWriter::writeVRT(
const QString &file )
962 QFile outputFile( file );
963 if ( ! outputFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
968 QTextStream outStream( &outputFile );
969 mVRTDocument.save( outStream, 2 );
974 int iterRows,
int iterLeft,
int iterTop,
const QString &outputUrl,
int fileIndex,
int nBands,
Qgis::DataType type,
977 double mup = extent.
width() / nCols;
978 double mapLeft = extent.
xMinimum() + iterLeft * mup;
979 double mapRight = mapLeft + mup * iterCols;
980 double mapTop = extent.
yMaximum() - iterTop * mup;
981 double mapBottom = mapTop - iterRows * mup;
982 QgsRectangle mapRect( mapLeft, mapBottom, mapRight, mapTop );
984 QString outputFile =
outputUrl +
'/' + partFileName( fileIndex );
987 double geoTransform[6];
988 geoTransform[0] = mapRect.xMinimum();
989 geoTransform[1] = mup;
990 geoTransform[2] = 0.0;
991 geoTransform[3] = mapRect.yMaximum();
992 geoTransform[4] = 0.0;
993 geoTransform[5] = -mup;
1000 return destProvider;
1005 const QList<bool> &destHasNoDataValueList,
const QList<double> &destNoDataValueList )
1009 createVRT( nCols, nRows,
crs, geoTransform, type, destHasNoDataValueList, destNoDataValueList );
1017 if ( mBuildPyramidsFlag == -4 && mOutputProviderKey ==
"gdal" && mOutputFormat.compare( QLatin1String(
"gtiff" ), Qt::CaseInsensitive ) == 0 )
1018 mCreateOptions <<
"COPY_SRC_OVERVIEWS=YES";
1023 if ( !destProvider )
1025 QgsDebugMsg( QStringLiteral(
"No provider created" ) );
1028 return destProvider;
1032 void QgsRasterFileWriter::globalOutputParameters(
const QgsRectangle &extent,
int nCols,
int &nRows,
1033 double *geoTransform,
double &pixelSize )
1035 pixelSize = extent.
width() / nCols;
1040 nRows =
static_cast< double >( nCols ) / extent.
width() * extent.
height() + 0.5;
1042 geoTransform[0] = extent.
xMinimum();
1043 geoTransform[1] = pixelSize;
1044 geoTransform[2] = 0.0;
1045 geoTransform[3] = extent.
yMaximum();
1046 geoTransform[4] = 0.0;
1047 geoTransform[5] = -( extent.
height() / nRows );
1050 QString QgsRasterFileWriter::partFileName(
int fileIndex )
1053 QFileInfo outputInfo( mOutputUrl );
1054 return QStringLiteral(
"%1.%2.tif" ).arg( outputInfo.fileName() ).arg( fileIndex );
1057 QString QgsRasterFileWriter::vrtFileName()
1059 QFileInfo outputInfo( mOutputUrl );
1060 return QStringLiteral(
"%1.vrt" ).arg( outputInfo.fileName() );
1065 QString ext = extension.trimmed();
1066 if ( ext.isEmpty() )
1069 if ( ext.startsWith(
'.' ) )
1073 int const drvCount = GDALGetDriverCount();
1075 for (
int i = 0; i < drvCount; ++i )
1077 GDALDriverH drv = GDALGetDriver( i );
1080 char **driverMetadata = GDALGetMetadata( drv,
nullptr );
1081 if ( CSLFetchBoolean( driverMetadata, GDAL_DCAP_RASTER,
false ) )
1083 QString drvName = GDALGetDriverShortName( drv );
1084 QStringList driverExtensions = QString( GDALGetMetadataItem( drv, GDAL_DMD_EXTENSIONS,
nullptr ) ).split(
' ' );
1086 const auto constDriverExtensions = driverExtensions;
1087 for (
const QString &driver : constDriverExtensions )
1089 if ( driver.compare( ext, Qt::CaseInsensitive ) == 0 )
1100 GDALDriverH drv = GDALGetDriverByName( format.toLocal8Bit().data() );
1103 char **driverMetadata = GDALGetMetadata( drv,
nullptr );
1104 if ( CSLFetchBoolean( driverMetadata, GDAL_DCAP_RASTER,
false ) )
1106 return QString( GDALGetMetadataItem( drv, GDAL_DMD_EXTENSIONS,
nullptr ) ).split(
' ' );
1109 return QStringList();
1114 GDALDriverH drv = GDALGetDriverByName( driverName.toLocal8Bit().data() );
1117 QString drvName = GDALGetDriverLongName( drv );
1118 QString extensionsString = QString( GDALGetMetadataItem( drv, GDAL_DMD_EXTENSIONS,
nullptr ) );
1119 if ( extensionsString.isEmpty() )
1123 QStringList extensions = extensionsString.split(
' ' );
1124 QString filter = drvName +
" (";
1125 for (
const QString &ext : extensions )
1127 filter.append( QStringLiteral(
"*.%1 *.%2 " ).arg( ext.toLower(), ext.toUpper() ) );
1129 filter = filter.trimmed().append( QStringLiteral(
")" ) );
1138 static QReadWriteLock sFilterLock;
1139 static QMap< RasterFormatOptions, QList< QgsRasterFileWriter::FilterFormatDetails > > sFilters;
1143 const auto it = sFilters.constFind( options );
1144 if ( it != sFilters.constEnd() )
1148 int const drvCount = GDALGetDriverCount();
1151 QList< QgsRasterFileWriter::FilterFormatDetails > results;
1155 for (
int i = 0; i < drvCount; ++i )
1157 GDALDriverH drv = GDALGetDriver( i );
1162 QString drvName = GDALGetDriverShortName( drv );
1164 if ( filterString.isEmpty() )
1173 if ( drvName == QLatin1String(
"GTiff" ) )
1175 tifFormat = details;
1187 return a.driverName < b.driverName;
1194 results.insert( 0, tifFormat );
1198 sFilters.insert( options, results );
1206 QStringList extensions;
1208 QRegularExpression rx( QStringLiteral(
"\\*\\.([a-zA-Z0-9]*)" ) );
1212 QString ext = format.filterString;
1213 QRegularExpressionMatch match = rx.match( ext );
1214 if ( !match.hasMatch() )
1217 QString matched = match.captured( 1 );
1218 extensions << matched;