28 #include <QCoreApplication>
29 #include <QProgressDialog>
30 #include <QTextStream>
31 #include <QMessageBox>
36 #include <cpl_string.h>
44 double geoTransform[6];
45 globalOutputParameters( extent, width, height, geoTransform, pixelSize );
47 return initOutput( width, height,
crs, geoTransform, 1, dataType, QList<bool>(), QList<double>() );
56 double geoTransform[6];
57 globalOutputParameters( extent, width, height, geoTransform, pixelSize );
59 return initOutput( width, height,
crs, geoTransform, nBands, dataType, QList<bool>(), QList<double>() );
63 : mOutputUrl( outputUrl )
68 QgsRasterFileWriter::QgsRasterFileWriter()
110 QgsDebugMsgLevel( QStringLiteral(
"reading from %1" ).arg(
typeid( *iface ).name() ), 4 );
114 QgsDebugMsg( QStringLiteral(
"iface->srcInput() == 0" ) );
119 QgsDebugMsgLevel( QStringLiteral(
"srcInput = %1" ).arg(
typeid( srcInput ).name() ), 4 );
122 mFeedback = feedback;
129 QFileInfo fileInfo( mOutputUrl );
130 if ( !fileInfo.exists() )
132 QDir dir = fileInfo.dir();
133 if ( !dir.mkdir( fileInfo.fileName() ) )
135 QgsDebugMsg(
"Cannot create output VRT directory " + fileInfo.fileName() +
" in " + dir.absolutePath() );
142 QFile pyramidFile( mOutputUrl + ( mTiledMode ?
".vrt.ovr" :
".ovr" ) );
143 if ( pyramidFile.exists() )
144 pyramidFile.remove();
145 pyramidFile.setFileName( mOutputUrl + ( mTiledMode ?
".vrt.rrd" :
".rrd" ) );
146 if ( pyramidFile.exists() )
147 pyramidFile.remove();
149 if ( mMode ==
Image )
151 WriterError e = writeImageRaster( &iter, nCols, nRows, outputExtent,
crs, feedback );
156 WriterError e = writeDataRaster( pipe, &iter, nCols, nRows, outputExtent,
crs, transformContext, feedback );
179 QgsDebugMsg( QStringLiteral(
"Cannot get source data provider" ) );
196 for (
int i = 2; i <= nBands; ++i )
208 QList<bool> destHasNoDataValueList;
209 QList<double> destNoDataValueList;
210 QList<Qgis::DataType> destDataTypeList;
211 destDataTypeList.reserve( nBands );
212 destHasNoDataValueList.reserve( nBands );
213 destNoDataValueList.reserve( nBands );
215 const bool isGpkgOutput = mOutputProviderKey ==
"gdal" &&
216 mOutputFormat.compare( QLatin1String(
"gpkg" ), Qt::CaseInsensitive ) == 0;
218 double geoTransform[6];
219 globalOutputParameters( outputExtent, nCols, nRows, geoTransform, pixelSize );
220 const auto srcProviderExtent( srcProvider->
extent() );
222 for (
int bandNo = 1; bandNo <= nBands; bandNo++ )
227 bool destHasNoDataValue =
false;
228 double destNoDataValue = std::numeric_limits<double>::quiet_NaN();
233 if ( srcHasNoDataValue )
238 destHasNoDataValue =
true;
240 else if ( nuller && !nuller->
noData( bandNo ).isEmpty() )
243 destNoDataValue = nuller->
noData( bandNo ).value( 0 ).min();
244 destHasNoDataValue =
true;
249 else if ( !( isGpkgOutput && destDataType ==
Qgis::Byte ) )
257 outputExtentInSrcCrs = ct.transformBoundingBox( outputExtent );
259 if ( !srcProviderExtent.contains( outputExtentInSrcCrs ) &&
260 ( std::fabs( srcProviderExtent.xMinimum() - outputExtentInSrcCrs.
xMinimum() ) > geoTransform[1] / 2 ||
261 std::fabs( srcProviderExtent.xMaximum() - outputExtentInSrcCrs.
xMaximum() ) > geoTransform[1] / 2 ||
262 std::fabs( srcProviderExtent.yMinimum() - outputExtentInSrcCrs.
yMinimum() ) > std::fabs( geoTransform[5] ) / 2 ||
263 std::fabs( srcProviderExtent.yMaximum() - outputExtentInSrcCrs.
yMaximum() ) > std::fabs( geoTransform[5] ) / 2 ) )
274 destNoDataValue = typeMinValue;
278 destNoDataValue = typeMaxValue;
285 destHasNoDataValue =
true;
289 if ( nuller && destHasNoDataValue )
294 QgsDebugMsgLevel( QStringLiteral(
"bandNo = %1 destDataType = %2 destHasNoDataValue = %3 destNoDataValue = %4" ).arg( bandNo ).arg( destDataType ).arg( destHasNoDataValue ).arg( destNoDataValue ), 4 );
295 destDataTypeList.append( destDataType );
296 destHasNoDataValueList.append( destHasNoDataValue );
297 destNoDataValueList.append( destNoDataValue );
302 for (
int i = 1; i < nBands; i++ )
304 if ( destDataTypeList.value( i ) > destDataType )
306 destDataType = destDataTypeList.value( i );
312 for (
int attempt = 0; attempt < 2; attempt ++ )
316 std::unique_ptr<QgsRasterDataProvider> destProvider(
317 initOutput( nCols, nRows,
crs, geoTransform, nBands, destDataType, destHasNoDataValueList, destNoDataValueList ) );
324 if ( !destProvider->isValid() )
326 if ( feedback && !destProvider->error().isEmpty() )
328 feedback->
appendError( destProvider->error().summary() );
332 if ( nCols != destProvider->xSize() || nRows != destProvider->ySize() )
334 QgsDebugMsg( QStringLiteral(
"Created raster does not have requested dimensions" ) );
337 feedback->
appendError( QObject::tr(
"Created raster does not have requested dimensions" ) );
341 if ( nBands != destProvider->bandCount() )
343 QgsDebugMsg( QStringLiteral(
"Created raster does not have requested band count" ) );
346 feedback->
appendError( QObject::tr(
"Created raster does not have requested band count" ) );
354 destDataType = destProvider->dataType( 1 );
358 error = writeDataRaster( pipe, iter, nCols, nRows, outputExtent,
crs, destDataType, destHasNoDataValueList, destNoDataValueList, destProvider.get(), feedback );
365 destProvider->remove();
366 destProvider.reset();
374 for (
int i = 0; i < nBands; i++ )
376 double destNoDataValue;
378 destDataTypeList.replace( i, destDataType );
379 destNoDataValueList.replace( i, destNoDataValue );
381 destDataType = destDataTypeList.value( 0 );
394 static int qgsDivRoundUp(
int a,
int b )
396 return a / b + ( ( ( a % b ) != 0 ) ? 1 : 0 );
401 int nCols,
int nRows,
405 const QList<bool> &destHasNoDataValueList,
406 const QList<double> &destNoDataValueList,
411 Q_UNUSED( destHasNoDataValueList )
425 std::vector< std::unique_ptr<QgsRasterBlock> > blockList;
426 std::vector< std::unique_ptr<QgsRasterBlock> > destBlockList;
428 blockList.resize( nBands );
429 destBlockList.resize( nBands );
431 for (
int i = 1; i <= nBands; ++i )
434 if ( destProvider && destHasNoDataValueList.value( i - 1 ) )
436 destProvider->
setNoDataValue( i, destNoDataValueList.value( i - 1 ) );
446 nParts = nPartsX * nPartsY;
453 for (
int i = 1; i <= nBands; ++i )
461 QString vrtFilePath( mOutputUrl +
'/' + vrtFileName() );
462 writeVRT( vrtFilePath );
465 buildPyramids( vrtFilePath );
472 buildPyramids( mOutputUrl, destProvider );
479 blockList[i - 1].reset( block );
483 if ( feedback && fileIndex < ( nParts - 1 ) )
485 feedback->
setProgress( 100.0 * fileIndex /
static_cast< double >( nParts ) );
493 for (
int i = 1; i <= nBands; ++i )
495 if ( srcProvider && srcProvider->
dataType( i ) == destDataType )
502 blockList[i - 1]->convert( destDataType );
504 destBlockList[i - 1] = std::move( blockList[i - 1] );
509 std::unique_ptr< QgsRasterDataProvider > partDestProvider( createPartProvider( outputExtent,
510 nCols, iterCols, iterRows,
511 iterLeft, iterTop, mOutputUrl,
512 fileIndex, nBands, destDataType,
crs ) );
514 if ( !partDestProvider || !partDestProvider->isValid() )
520 for (
int i = 1; i <= nBands; ++i )
522 if ( destHasNoDataValueList.value( i - 1 ) )
524 partDestProvider->setNoDataValue( i, destNoDataValueList.value( i - 1 ) );
526 if ( destBlockList[ i - 1 ]->isEmpty() )
529 if ( !partDestProvider->write( destBlockList[i - 1]->bits( 0 ), i, iterCols, iterRows, 0, 0 ) )
533 addToVRT( partFileName( fileIndex ), i, iterCols, iterRows, iterLeft, iterTop );
537 else if ( destProvider )
540 for (
int i = 1; i <= nBands; ++i )
542 if ( destBlockList[ i - 1 ]->isEmpty() )
545 if ( !destProvider->
write( destBlockList[i - 1]->bits( 0 ), i, iterCols, iterRows, iterLeft, iterTop ) )
581 const size_t nMaxPixels =
static_cast<size_t>( mMaxTileWidth ) * mMaxTileHeight;
582 std::vector<unsigned char> redData( nMaxPixels );
583 std::vector<unsigned char> greenData( nMaxPixels );
584 std::vector<unsigned char> blueData( nMaxPixels );
585 std::vector<unsigned char> alphaData( nMaxPixels );
586 int iterLeft = 0, iterTop = 0, iterCols = 0, iterRows = 0;
591 double geoTransform[6];
592 globalOutputParameters( outputExtent, nCols, nRows, geoTransform, pixelSize );
594 const int nOutputBands = 4;
595 std::unique_ptr< QgsRasterDataProvider > destProvider( initOutput( nCols, nRows,
crs, geoTransform, nOutputBands,
Qgis::Byte ) );
602 if ( !destProvider->
isValid() )
610 if ( nCols != destProvider->
xSize() || nRows != destProvider->
ySize() )
612 QgsDebugMsg( QStringLiteral(
"Created raster does not have requested dimensions" ) );
615 feedback->
appendError( QObject::tr(
"Created raster does not have requested dimensions" ) );
619 if ( nOutputBands != destProvider->
bandCount() )
621 QgsDebugMsg( QStringLiteral(
"Created raster does not have requested band count" ) );
624 feedback->
appendError( QObject::tr(
"Created raster does not have requested band count" ) );
630 QgsDebugMsg( QStringLiteral(
"Created raster does not have requested data type" ) );
633 feedback->
appendError( QObject::tr(
"Created raster does not have requested data type" ) );
646 nParts = nPartsX * nPartsY;
649 std::unique_ptr< QgsRasterBlock > inputBlock;
650 while ( iter->
readNextRasterPart( 1, iterCols, iterRows, inputBlock, iterLeft, iterTop ) )
652 if ( !inputBlock || inputBlock->isEmpty() )
657 if ( feedback && fileIndex < ( nParts - 1 ) )
659 feedback->
setProgress( 100.0 * fileIndex /
static_cast< double >( nParts ) );
668 for (
qgssize i = 0; i < nPixels; ++i )
670 QRgb
c = inputBlock->color( i );
671 if ( isPremultiplied )
673 c = qUnpremultiply(
c );
675 redData[i] =
static_cast<unsigned char>( qRed(
c ) );
676 greenData[i] =
static_cast<unsigned char>( qGreen(
c ) );
677 blueData[i] =
static_cast<unsigned char>( qBlue(
c ) );
678 alphaData[i] =
static_cast<unsigned char>( qAlpha(
c ) );
684 std::unique_ptr< QgsRasterDataProvider > partDestProvider( createPartProvider( outputExtent,
685 nCols, iterCols, iterRows,
686 iterLeft, iterTop, mOutputUrl, fileIndex,
689 if ( !partDestProvider || partDestProvider->isValid() )
695 if ( !partDestProvider->write( &redData[0], 1, iterCols, iterRows, 0, 0 ) ||
696 !partDestProvider->write( &greenData[0], 2, iterCols, iterRows, 0, 0 ) ||
697 !partDestProvider->write( &blueData[0], 3, iterCols, iterRows, 0, 0 ) ||
698 !partDestProvider->write( &alphaData[0], 4, iterCols, iterRows, 0, 0 ) )
703 addToVRT( partFileName( fileIndex ), 1, iterCols, iterRows, iterLeft, iterTop );
704 addToVRT( partFileName( fileIndex ), 2, iterCols, iterRows, iterLeft, iterTop );
705 addToVRT( partFileName( fileIndex ), 3, iterCols, iterRows, iterLeft, iterTop );
706 addToVRT( partFileName( fileIndex ), 4, iterCols, iterRows, iterLeft, iterTop );
708 else if ( destProvider )
710 if ( !destProvider->
write( &redData[0], 1, iterCols, iterRows, iterLeft, iterTop ) ||
711 !destProvider->
write( &greenData[0], 2, iterCols, iterRows, iterLeft, iterTop ) ||
712 !destProvider->
write( &blueData[0], 3, iterCols, iterRows, iterLeft, iterTop ) ||
713 !destProvider->
write( &alphaData[0], 4, iterCols, iterRows, iterLeft, iterTop ) )
721 destProvider.reset();
730 QString vrtFilePath( mOutputUrl +
'/' + vrtFileName() );
731 writeVRT( vrtFilePath );
734 buildPyramids( vrtFilePath );
741 buildPyramids( mOutputUrl );
747 void QgsRasterFileWriter::addToVRT(
const QString &filename,
int band,
int xSize,
int ySize,
int xOffset,
int yOffset )
749 QDomElement bandElem = mVRTBands.value( band - 1 );
751 QDomElement simpleSourceElem = mVRTDocument.createElement( QStringLiteral(
"SimpleSource" ) );
754 QDomElement sourceFilenameElem = mVRTDocument.createElement( QStringLiteral(
"SourceFilename" ) );
755 sourceFilenameElem.setAttribute( QStringLiteral(
"relativeToVRT" ), QStringLiteral(
"1" ) );
756 QDomText sourceFilenameText = mVRTDocument.createTextNode( filename );
757 sourceFilenameElem.appendChild( sourceFilenameText );
758 simpleSourceElem.appendChild( sourceFilenameElem );
761 QDomElement sourceBandElem = mVRTDocument.createElement( QStringLiteral(
"SourceBand" ) );
762 QDomText sourceBandText = mVRTDocument.createTextNode( QString::number( band ) );
763 sourceBandElem.appendChild( sourceBandText );
764 simpleSourceElem.appendChild( sourceBandElem );
767 QDomElement sourcePropertiesElem = mVRTDocument.createElement( QStringLiteral(
"SourceProperties" ) );
768 sourcePropertiesElem.setAttribute( QStringLiteral(
"RasterXSize" ), xSize );
769 sourcePropertiesElem.setAttribute( QStringLiteral(
"RasterYSize" ), ySize );
770 sourcePropertiesElem.setAttribute( QStringLiteral(
"BlockXSize" ), xSize );
771 sourcePropertiesElem.setAttribute( QStringLiteral(
"BlockYSize" ), ySize );
772 sourcePropertiesElem.setAttribute( QStringLiteral(
"DataType" ), QStringLiteral(
"Byte" ) );
773 simpleSourceElem.appendChild( sourcePropertiesElem );
776 QDomElement srcRectElem = mVRTDocument.createElement( QStringLiteral(
"SrcRect" ) );
777 srcRectElem.setAttribute( QStringLiteral(
"xOff" ), QStringLiteral(
"0" ) );
778 srcRectElem.setAttribute( QStringLiteral(
"yOff" ), QStringLiteral(
"0" ) );
779 srcRectElem.setAttribute( QStringLiteral(
"xSize" ), xSize );
780 srcRectElem.setAttribute( QStringLiteral(
"ySize" ), ySize );
781 simpleSourceElem.appendChild( srcRectElem );
784 QDomElement dstRectElem = mVRTDocument.createElement( QStringLiteral(
"DstRect" ) );
785 dstRectElem.setAttribute( QStringLiteral(
"xOff" ), xOffset );
786 dstRectElem.setAttribute( QStringLiteral(
"yOff" ), yOffset );
787 dstRectElem.setAttribute( QStringLiteral(
"xSize" ), xSize );
788 dstRectElem.setAttribute( QStringLiteral(
"ySize" ), ySize );
789 simpleSourceElem.appendChild( dstRectElem );
791 bandElem.appendChild( simpleSourceElem );
794 void QgsRasterFileWriter::buildPyramids(
const QString &filename,
QgsRasterDataProvider *destProviderIn )
802 destProvider = qobject_cast< QgsRasterDataProvider * >(
QgsProviderRegistry::instance()->createProvider( mOutputProviderKey, filename, providerOptions ) );
803 if ( !destProvider || !destProvider->
isValid() )
813 QList< QgsRasterPyramid> myPyramidList;
814 if ( ! mPyramidsList.isEmpty() )
816 for (
int myCounterInt = 0; myCounterInt < myPyramidList.count(); myCounterInt++ )
818 myPyramidList[myCounterInt].build =
true;
821 QgsDebugMsgLevel( QStringLiteral(
"building pyramids : %1 pyramids, %2 resampling, %3 format, %4 options" ).arg( myPyramidList.count() ).arg( mPyramidsResampling ).arg( mPyramidsFormat ).arg( mPyramidsConfigOptions.count() ), 4 );
823 QString res = destProvider->
buildPyramids( myPyramidList, mPyramidsResampling,
824 mPyramidsFormat, mPyramidsConfigOptions );
830 QString title, message;
831 if ( res == QLatin1String(
"ERROR_WRITE_ACCESS" ) )
833 title = QObject::tr(
"Building Pyramids" );
834 message = QObject::tr(
"Write access denied. Adjust the file permissions and try again." );
836 else if ( res == QLatin1String(
"ERROR_WRITE_FORMAT" ) )
838 title = QObject::tr(
"Building Pyramids" );
839 message = QObject::tr(
"The file was not writable. Some formats do not "
840 "support pyramid overviews. Consult the GDAL documentation if in doubt." );
842 else if ( res == QLatin1String(
"FAILED_NOT_SUPPORTED" ) )
844 title = QObject::tr(
"Building Pyramids" );
845 message = QObject::tr(
"Building pyramid overviews is not supported on this type of raster." );
847 else if ( res == QLatin1String(
"ERROR_VIRTUAL" ) )
849 title = QObject::tr(
"Building Pyramids" );
850 message = QObject::tr(
"Building pyramid overviews is not supported on this type of raster." );
852 QMessageBox::warning(
nullptr, title, message );
855 if ( !destProviderIn )
860 int QgsRasterFileWriter::pyramidsProgress(
double dfComplete,
const char *pszMessage,
void *pData )
862 Q_UNUSED( pszMessage )
863 GDALTermProgress( dfComplete, 0, 0 );
864 QProgressDialog *progressDialog =
static_cast<QProgressDialog *
>( pData );
865 if ( pData && progressDialog->wasCanceled() )
872 progressDialog->setRange( 0, 100 );
873 progressDialog->setValue( dfComplete * 100 );
879 void QgsRasterFileWriter::createVRT(
int xSize,
int ySize,
const QgsCoordinateReferenceSystem &
crs,
double *geoTransform,
Qgis::DataType type,
const QList<bool> &destHasNoDataValueList,
const QList<double> &destNoDataValueList )
881 mVRTDocument.clear();
882 QDomElement VRTDatasetElem = mVRTDocument.createElement( QStringLiteral(
"VRTDataset" ) );
885 VRTDatasetElem.setAttribute( QStringLiteral(
"rasterXSize" ), xSize );
886 VRTDatasetElem.setAttribute( QStringLiteral(
"rasterYSize" ), ySize );
887 mVRTDocument.appendChild( VRTDatasetElem );
890 QDomElement SRSElem = mVRTDocument.createElement( QStringLiteral(
"SRS" ) );
891 QDomText crsText = mVRTDocument.createTextNode(
crs.
toWkt() );
892 SRSElem.appendChild( crsText );
893 VRTDatasetElem.appendChild( SRSElem );
898 QDomElement geoTransformElem = mVRTDocument.createElement( QStringLiteral(
"GeoTransform" ) );
899 QString geoTransformString = QString::number( geoTransform[0],
'f', 6 ) +
", " + QString::number( geoTransform[1] ) +
", " + QString::number( geoTransform[2] ) +
900 ", " + QString::number( geoTransform[3],
'f', 6 ) +
", " + QString::number( geoTransform[4] ) +
", " + QString::number( geoTransform[5] );
901 QDomText geoTransformText = mVRTDocument.createTextNode( geoTransformString );
902 geoTransformElem.appendChild( geoTransformText );
903 VRTDatasetElem.appendChild( geoTransformElem );
916 QStringList colorInterp;
917 colorInterp << QStringLiteral(
"Red" ) << QStringLiteral(
"Green" ) << QStringLiteral(
"Blue" ) << QStringLiteral(
"Alpha" );
919 QMap<Qgis::DataType, QString> dataTypes;
920 dataTypes.insert(
Qgis::Byte, QStringLiteral(
"Byte" ) );
921 dataTypes.insert(
Qgis::UInt16, QStringLiteral(
"UInt16" ) );
922 dataTypes.insert(
Qgis::Int16, QStringLiteral(
"Int16" ) );
923 dataTypes.insert(
Qgis::UInt32, QStringLiteral(
"Int32" ) );
924 dataTypes.insert(
Qgis::Float32, QStringLiteral(
"Float32" ) );
925 dataTypes.insert(
Qgis::Float64, QStringLiteral(
"Float64" ) );
926 dataTypes.insert(
Qgis::CInt16, QStringLiteral(
"CInt16" ) );
927 dataTypes.insert(
Qgis::CInt32, QStringLiteral(
"CInt32" ) );
931 for (
int i = 1; i <= nBands; i++ )
933 QDomElement VRTBand = mVRTDocument.createElement( QStringLiteral(
"VRTRasterBand" ) );
935 VRTBand.setAttribute( QStringLiteral(
"band" ), QString::number( i ) );
936 QString dataType = dataTypes.value( type );
937 VRTBand.setAttribute( QStringLiteral(
"dataType" ), dataType );
939 if ( mMode ==
Image )
941 VRTBand.setAttribute( QStringLiteral(
"dataType" ), QStringLiteral(
"Byte" ) );
942 QDomElement colorInterpElement = mVRTDocument.createElement( QStringLiteral(
"ColorInterp" ) );
943 QDomText interpText = mVRTDocument.createTextNode( colorInterp.value( i - 1 ) );
944 colorInterpElement.appendChild( interpText );
945 VRTBand.appendChild( colorInterpElement );
948 if ( !destHasNoDataValueList.isEmpty() && destHasNoDataValueList.value( i - 1 ) )
950 VRTBand.setAttribute( QStringLiteral(
"NoDataValue" ), QString::number( destNoDataValueList.value( i - 1 ) ) );
953 mVRTBands.append( VRTBand );
954 VRTDatasetElem.appendChild( VRTBand );
958 bool QgsRasterFileWriter::writeVRT(
const QString &file )
960 QFile outputFile( file );
961 if ( ! outputFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
966 QTextStream outStream( &outputFile );
967 mVRTDocument.save( outStream, 2 );
972 int iterRows,
int iterLeft,
int iterTop,
const QString &outputUrl,
int fileIndex,
int nBands,
Qgis::DataType type,
975 double mup = extent.
width() / nCols;
976 double mapLeft = extent.
xMinimum() + iterLeft * mup;
977 double mapRight = mapLeft + mup * iterCols;
978 double mapTop = extent.
yMaximum() - iterTop * mup;
979 double mapBottom = mapTop - iterRows * mup;
980 QgsRectangle mapRect( mapLeft, mapBottom, mapRight, mapTop );
982 QString outputFile =
outputUrl +
'/' + partFileName( fileIndex );
985 double geoTransform[6];
986 geoTransform[0] = mapRect.xMinimum();
987 geoTransform[1] = mup;
988 geoTransform[2] = 0.0;
989 geoTransform[3] = mapRect.yMaximum();
990 geoTransform[4] = 0.0;
991 geoTransform[5] = -mup;
1003 const QList<bool> &destHasNoDataValueList,
const QList<double> &destNoDataValueList )
1007 createVRT( nCols, nRows,
crs, geoTransform, type, destHasNoDataValueList, destNoDataValueList );
1015 if ( mBuildPyramidsFlag == -4 && mOutputProviderKey ==
"gdal" && mOutputFormat.compare( QLatin1String(
"gtiff" ), Qt::CaseInsensitive ) == 0 )
1016 mCreateOptions <<
"COPY_SRC_OVERVIEWS=YES";
1021 if ( !destProvider )
1023 QgsDebugMsg( QStringLiteral(
"No provider created" ) );
1026 return destProvider;
1030 void QgsRasterFileWriter::globalOutputParameters(
const QgsRectangle &extent,
int nCols,
int &nRows,
1031 double *geoTransform,
double &pixelSize )
1033 pixelSize = extent.
width() / nCols;
1038 nRows =
static_cast< double >( nCols ) / extent.
width() * extent.
height() + 0.5;
1040 geoTransform[0] = extent.
xMinimum();
1041 geoTransform[1] = pixelSize;
1042 geoTransform[2] = 0.0;
1043 geoTransform[3] = extent.
yMaximum();
1044 geoTransform[4] = 0.0;
1045 geoTransform[5] = -( extent.
height() / nRows );
1048 QString QgsRasterFileWriter::partFileName(
int fileIndex )
1051 QFileInfo outputInfo( mOutputUrl );
1052 return QStringLiteral(
"%1.%2.tif" ).arg( outputInfo.fileName() ).arg( fileIndex );
1055 QString QgsRasterFileWriter::vrtFileName()
1057 QFileInfo outputInfo( mOutputUrl );
1058 return QStringLiteral(
"%1.vrt" ).arg( outputInfo.fileName() );
1063 QString ext = extension.trimmed();
1064 if ( ext.isEmpty() )
1067 if ( ext.startsWith(
'.' ) )
1071 int const drvCount = GDALGetDriverCount();
1073 for (
int i = 0; i < drvCount; ++i )
1075 GDALDriverH drv = GDALGetDriver( i );
1078 char **driverMetadata = GDALGetMetadata( drv,
nullptr );
1079 if ( CSLFetchBoolean( driverMetadata, GDAL_DCAP_RASTER,
false ) )
1081 QString drvName = GDALGetDriverShortName( drv );
1082 QStringList driverExtensions = QString( GDALGetMetadataItem( drv, GDAL_DMD_EXTENSIONS,
nullptr ) ).split(
' ' );
1084 const auto constDriverExtensions = driverExtensions;
1085 for (
const QString &driver : constDriverExtensions )
1087 if ( driver.compare( ext, Qt::CaseInsensitive ) == 0 )
1098 GDALDriverH drv = GDALGetDriverByName( format.toLocal8Bit().data() );
1101 char **driverMetadata = GDALGetMetadata( drv,
nullptr );
1102 if ( CSLFetchBoolean( driverMetadata, GDAL_DCAP_RASTER,
false ) )
1104 return QString( GDALGetMetadataItem( drv, GDAL_DMD_EXTENSIONS,
nullptr ) ).split(
' ' );
1107 return QStringList();
1112 GDALDriverH drv = GDALGetDriverByName( driverName.toLocal8Bit().data() );
1115 QString drvName = GDALGetDriverLongName( drv );
1116 QString extensionsString = QString( GDALGetMetadataItem( drv, GDAL_DMD_EXTENSIONS,
nullptr ) );
1117 if ( extensionsString.isEmpty() )
1121 QStringList extensions = extensionsString.split(
' ' );
1122 QString filter = drvName +
" (";
1123 for (
const QString &ext : extensions )
1125 filter.append( QStringLiteral(
"*.%1 *.%2 " ).arg( ext.toLower(), ext.toUpper() ) );
1127 filter = filter.trimmed().append( QStringLiteral(
")" ) );
1136 QList< FilterFormatDetails > results;
1139 int const drvCount = GDALGetDriverCount();
1143 for (
int i = 0; i < drvCount; ++i )
1145 GDALDriverH drv = GDALGetDriver( i );
1150 QString drvName = GDALGetDriverShortName( drv );
1152 if ( filterString.isEmpty() )
1161 if ( drvName == QLatin1String(
"GTiff" ) )
1163 tifFormat = details;
1175 return a.driverName < b.driverName;
1182 results.insert( 0, tifFormat );
1192 QStringList extensions;
1194 QRegularExpression rx( QStringLiteral(
"\\*\\.([a-zA-Z0-9]*)" ) );
1198 QString ext = format.filterString;
1199 QRegularExpressionMatch match = rx.match( ext );
1200 if ( !match.hasMatch() )
1203 QString matched = match.captured( 1 );
1204 extensions << matched;