29 #include <QCoreApplication>
30 #include <QProgressDialog>
31 #include <QTextStream>
32 #include <QMessageBox>
33 #include <QRegularExpression>
38 #include <cpl_string.h>
47 double geoTransform[6];
48 globalOutputParameters( extent, width, height, geoTransform, pixelSize );
50 return initOutput( width, height,
crs, geoTransform, 1, dataType, QList<bool>(), QList<double>() );
59 double geoTransform[6];
60 globalOutputParameters( extent, width, height, geoTransform, pixelSize );
62 return initOutput( width, height,
crs, geoTransform, nBands, dataType, QList<bool>(), QList<double>() );
66 : mOutputUrl( outputUrl )
71 QgsRasterFileWriter::QgsRasterFileWriter()
113 QgsDebugMsgLevel( QStringLiteral(
"reading from %1" ).arg(
typeid( *iface ).name() ), 4 );
117 QgsDebugMsg( QStringLiteral(
"iface->srcInput() == 0" ) );
122 QgsDebugMsgLevel( QStringLiteral(
"srcInput = %1" ).arg(
typeid( srcInput ).name() ), 4 );
125 mFeedback = feedback;
132 QFileInfo fileInfo( mOutputUrl );
133 if ( !fileInfo.exists() )
135 QDir dir = fileInfo.dir();
136 if ( !dir.mkdir( fileInfo.fileName() ) )
138 QgsDebugMsg(
"Cannot create output VRT directory " + fileInfo.fileName() +
" in " + dir.absolutePath() );
145 QFile pyramidFile( mOutputUrl + ( mTiledMode ?
".vrt.ovr" :
".ovr" ) );
146 if ( pyramidFile.exists() )
147 pyramidFile.remove();
148 pyramidFile.setFileName( mOutputUrl + ( mTiledMode ?
".vrt.rrd" :
".rrd" ) );
149 if ( pyramidFile.exists() )
150 pyramidFile.remove();
152 if ( mMode ==
Image )
154 WriterError e = writeImageRaster( &iter, nCols, nRows, outputExtent,
crs, feedback );
159 WriterError e = writeDataRaster( pipe, &iter, nCols, nRows, outputExtent,
crs, transformContext, feedback );
182 QgsDebugMsg( QStringLiteral(
"Cannot get source data provider" ) );
199 for (
int i = 2; i <= nBands; ++i )
211 QList<bool> destHasNoDataValueList;
212 QList<double> destNoDataValueList;
213 QList<Qgis::DataType> destDataTypeList;
214 destDataTypeList.reserve( nBands );
215 destHasNoDataValueList.reserve( nBands );
216 destNoDataValueList.reserve( nBands );
218 const bool isGpkgOutput = mOutputProviderKey ==
"gdal" &&
219 mOutputFormat.compare( QLatin1String(
"gpkg" ), Qt::CaseInsensitive ) == 0;
221 double geoTransform[6];
222 globalOutputParameters( outputExtent, nCols, nRows, geoTransform, pixelSize );
223 const auto srcProviderExtent( srcProvider->
extent() );
225 for (
int bandNo = 1; bandNo <= nBands; bandNo++ )
230 bool destHasNoDataValue =
false;
231 double destNoDataValue = std::numeric_limits<double>::quiet_NaN();
236 if ( srcHasNoDataValue )
241 destHasNoDataValue =
true;
243 else if ( nuller && !nuller->
noData( bandNo ).isEmpty() )
246 destNoDataValue = nuller->
noData( bandNo ).value( 0 ).min();
247 destHasNoDataValue =
true;
260 outputExtentInSrcCrs = ct.transformBoundingBox( outputExtent );
262 if ( !srcProviderExtent.contains( outputExtentInSrcCrs ) &&
263 ( std::fabs( srcProviderExtent.xMinimum() - outputExtentInSrcCrs.
xMinimum() ) > geoTransform[1] / 2 ||
264 std::fabs( srcProviderExtent.xMaximum() - outputExtentInSrcCrs.
xMaximum() ) > geoTransform[1] / 2 ||
265 std::fabs( srcProviderExtent.yMinimum() - outputExtentInSrcCrs.
yMinimum() ) > std::fabs( geoTransform[5] ) / 2 ||
266 std::fabs( srcProviderExtent.yMaximum() - outputExtentInSrcCrs.
yMaximum() ) > std::fabs( geoTransform[5] ) / 2 ) )
277 destNoDataValue = typeMinValue;
281 destNoDataValue = typeMaxValue;
288 destHasNoDataValue =
true;
292 if ( nuller && destHasNoDataValue )
297 QgsDebugMsgLevel( QStringLiteral(
"bandNo = %1 destDataType = %2 destHasNoDataValue = %3 destNoDataValue = %4" ).arg( bandNo ).arg(
qgsEnumValueToKey( destDataType ) ).arg( destHasNoDataValue ).arg( destNoDataValue ), 4 );
298 destDataTypeList.append( destDataType );
299 destHasNoDataValueList.append( destHasNoDataValue );
300 destNoDataValueList.append( destNoDataValue );
305 for (
int i = 1; i < nBands; i++ )
307 if ( destDataTypeList.value( i ) > destDataType )
309 destDataType = destDataTypeList.value( i );
315 for (
int attempt = 0; attempt < 2; attempt ++ )
319 std::unique_ptr<QgsRasterDataProvider> destProvider(
320 initOutput( nCols, nRows,
crs, geoTransform, nBands, destDataType, destHasNoDataValueList, destNoDataValueList ) );
327 if ( !destProvider->isValid() )
329 if ( feedback && !destProvider->error().isEmpty() )
331 feedback->
appendError( destProvider->error().summary() );
335 if ( nCols != destProvider->xSize() || nRows != destProvider->ySize() )
337 QgsDebugMsg( QStringLiteral(
"Created raster does not have requested dimensions" ) );
340 feedback->
appendError( QObject::tr(
"Created raster does not have requested dimensions" ) );
344 if ( nBands != destProvider->bandCount() )
346 QgsDebugMsg( QStringLiteral(
"Created raster does not have requested band count" ) );
349 feedback->
appendError( QObject::tr(
"Created raster does not have requested band count" ) );
357 destDataType = destProvider->dataType( 1 );
361 error = writeDataRaster( pipe, iter, nCols, nRows, outputExtent,
crs, destDataType, destHasNoDataValueList, destNoDataValueList, destProvider.get(), feedback );
368 destProvider->remove();
369 destProvider.reset();
377 for (
int i = 0; i < nBands; i++ )
379 double destNoDataValue;
381 destDataTypeList.replace( i, destDataType );
382 destNoDataValueList.replace( i, destNoDataValue );
384 destDataType = destDataTypeList.value( 0 );
397 static int qgsDivRoundUp(
int a,
int b )
399 return a / b + ( ( ( a % b ) != 0 ) ? 1 : 0 );
404 int nCols,
int nRows,
408 const QList<bool> &destHasNoDataValueList,
409 const QList<double> &destNoDataValueList,
414 Q_UNUSED( destHasNoDataValueList )
428 std::vector< std::unique_ptr<QgsRasterBlock> > blockList;
429 std::vector< std::unique_ptr<QgsRasterBlock> > destBlockList;
431 blockList.resize( nBands );
432 destBlockList.resize( nBands );
434 for (
int i = 1; i <= nBands; ++i )
437 if ( destProvider && destHasNoDataValueList.value( i - 1 ) )
439 destProvider->
setNoDataValue( i, destNoDataValueList.value( i - 1 ) );
449 nParts = nPartsX * nPartsY;
456 for (
int i = 1; i <= nBands; ++i )
464 QString vrtFilePath( mOutputUrl +
'/' + vrtFileName() );
465 writeVRT( vrtFilePath );
468 buildPyramids( vrtFilePath );
475 buildPyramids( mOutputUrl, destProvider );
482 blockList[i - 1].reset( block );
486 if ( feedback && fileIndex < ( nParts - 1 ) )
488 feedback->
setProgress( 100.0 * fileIndex /
static_cast< double >( nParts ) );
496 for (
int i = 1; i <= nBands; ++i )
498 if ( srcProvider && srcProvider->
dataType( i ) == destDataType )
505 blockList[i - 1]->convert( destDataType );
507 destBlockList[i - 1] = std::move( blockList[i - 1] );
512 std::unique_ptr< QgsRasterDataProvider > partDestProvider( createPartProvider( outputExtent,
513 nCols, iterCols, iterRows,
514 iterLeft, iterTop, mOutputUrl,
515 fileIndex, nBands, destDataType,
crs ) );
517 if ( !partDestProvider || !partDestProvider->isValid() )
523 for (
int i = 1; i <= nBands; ++i )
525 if ( destHasNoDataValueList.value( i - 1 ) )
527 partDestProvider->setNoDataValue( i, destNoDataValueList.value( i - 1 ) );
529 if ( destBlockList[ i - 1 ]->isEmpty() )
532 if ( !partDestProvider->write( destBlockList[i - 1]->bits( 0 ), i, iterCols, iterRows, 0, 0 ) )
536 addToVRT( partFileName( fileIndex ), i, iterCols, iterRows, iterLeft, iterTop );
540 else if ( destProvider )
543 for (
int i = 1; i <= nBands; ++i )
545 if ( destBlockList[ i - 1 ]->isEmpty() )
548 if ( !destProvider->
write( destBlockList[i - 1]->bits( 0 ), i, iterCols, iterRows, iterLeft, iterTop ) )
584 const size_t nMaxPixels =
static_cast<size_t>( mMaxTileWidth ) * mMaxTileHeight;
585 std::vector<unsigned char> redData( nMaxPixels );
586 std::vector<unsigned char> greenData( nMaxPixels );
587 std::vector<unsigned char> blueData( nMaxPixels );
588 std::vector<unsigned char> alphaData( nMaxPixels );
589 int iterLeft = 0, iterTop = 0, iterCols = 0, iterRows = 0;
594 double geoTransform[6];
595 globalOutputParameters( outputExtent, nCols, nRows, geoTransform, pixelSize );
597 const int nOutputBands = 4;
598 std::unique_ptr< QgsRasterDataProvider > destProvider( initOutput( nCols, nRows,
crs, geoTransform, nOutputBands,
Qgis::DataType::Byte ) );
605 if ( !destProvider->
isValid() )
613 if ( nCols != destProvider->
xSize() || nRows != destProvider->
ySize() )
615 QgsDebugMsg( QStringLiteral(
"Created raster does not have requested dimensions" ) );
618 feedback->
appendError( QObject::tr(
"Created raster does not have requested dimensions" ) );
622 if ( nOutputBands != destProvider->
bandCount() )
624 QgsDebugMsg( QStringLiteral(
"Created raster does not have requested band count" ) );
627 feedback->
appendError( QObject::tr(
"Created raster does not have requested band count" ) );
633 QgsDebugMsg( QStringLiteral(
"Created raster does not have requested data type" ) );
636 feedback->
appendError( QObject::tr(
"Created raster does not have requested data type" ) );
649 nParts = nPartsX * nPartsY;
652 std::unique_ptr< QgsRasterBlock > inputBlock;
653 while ( iter->
readNextRasterPart( 1, iterCols, iterRows, inputBlock, iterLeft, iterTop ) )
655 if ( !inputBlock || inputBlock->isEmpty() )
660 if ( feedback && fileIndex < ( nParts - 1 ) )
662 feedback->
setProgress( 100.0 * fileIndex /
static_cast< double >( nParts ) );
671 for (
qgssize i = 0; i < nPixels; ++i )
673 QRgb
c = inputBlock->color( i );
674 if ( isPremultiplied )
676 c = qUnpremultiply(
c );
678 redData[i] =
static_cast<unsigned char>( qRed(
c ) );
679 greenData[i] =
static_cast<unsigned char>( qGreen(
c ) );
680 blueData[i] =
static_cast<unsigned char>( qBlue(
c ) );
681 alphaData[i] =
static_cast<unsigned char>( qAlpha(
c ) );
687 std::unique_ptr< QgsRasterDataProvider > partDestProvider( createPartProvider( outputExtent,
688 nCols, iterCols, iterRows,
689 iterLeft, iterTop, mOutputUrl, fileIndex,
692 if ( !partDestProvider || partDestProvider->isValid() )
698 if ( !partDestProvider->write( &redData[0], 1, iterCols, iterRows, 0, 0 ) ||
699 !partDestProvider->write( &greenData[0], 2, iterCols, iterRows, 0, 0 ) ||
700 !partDestProvider->write( &blueData[0], 3, iterCols, iterRows, 0, 0 ) ||
701 !partDestProvider->write( &alphaData[0], 4, iterCols, iterRows, 0, 0 ) )
706 addToVRT( partFileName( fileIndex ), 1, iterCols, iterRows, iterLeft, iterTop );
707 addToVRT( partFileName( fileIndex ), 2, iterCols, iterRows, iterLeft, iterTop );
708 addToVRT( partFileName( fileIndex ), 3, iterCols, iterRows, iterLeft, iterTop );
709 addToVRT( partFileName( fileIndex ), 4, iterCols, iterRows, iterLeft, iterTop );
711 else if ( destProvider )
713 if ( !destProvider->
write( &redData[0], 1, iterCols, iterRows, iterLeft, iterTop ) ||
714 !destProvider->
write( &greenData[0], 2, iterCols, iterRows, iterLeft, iterTop ) ||
715 !destProvider->
write( &blueData[0], 3, iterCols, iterRows, iterLeft, iterTop ) ||
716 !destProvider->
write( &alphaData[0], 4, iterCols, iterRows, iterLeft, iterTop ) )
724 destProvider.reset();
733 QString vrtFilePath( mOutputUrl +
'/' + vrtFileName() );
734 writeVRT( vrtFilePath );
737 buildPyramids( vrtFilePath );
744 buildPyramids( mOutputUrl );
750 void QgsRasterFileWriter::addToVRT(
const QString &filename,
int band,
int xSize,
int ySize,
int xOffset,
int yOffset )
752 QDomElement bandElem = mVRTBands.value( band - 1 );
754 QDomElement simpleSourceElem = mVRTDocument.createElement( QStringLiteral(
"SimpleSource" ) );
757 QDomElement sourceFilenameElem = mVRTDocument.createElement( QStringLiteral(
"SourceFilename" ) );
758 sourceFilenameElem.setAttribute( QStringLiteral(
"relativeToVRT" ), QStringLiteral(
"1" ) );
759 QDomText sourceFilenameText = mVRTDocument.createTextNode( filename );
760 sourceFilenameElem.appendChild( sourceFilenameText );
761 simpleSourceElem.appendChild( sourceFilenameElem );
764 QDomElement sourceBandElem = mVRTDocument.createElement( QStringLiteral(
"SourceBand" ) );
765 QDomText sourceBandText = mVRTDocument.createTextNode( QString::number( band ) );
766 sourceBandElem.appendChild( sourceBandText );
767 simpleSourceElem.appendChild( sourceBandElem );
770 QDomElement sourcePropertiesElem = mVRTDocument.createElement( QStringLiteral(
"SourceProperties" ) );
771 sourcePropertiesElem.setAttribute( QStringLiteral(
"RasterXSize" ), xSize );
772 sourcePropertiesElem.setAttribute( QStringLiteral(
"RasterYSize" ), ySize );
773 sourcePropertiesElem.setAttribute( QStringLiteral(
"BlockXSize" ), xSize );
774 sourcePropertiesElem.setAttribute( QStringLiteral(
"BlockYSize" ), ySize );
775 sourcePropertiesElem.setAttribute( QStringLiteral(
"DataType" ), QStringLiteral(
"Byte" ) );
776 simpleSourceElem.appendChild( sourcePropertiesElem );
779 QDomElement srcRectElem = mVRTDocument.createElement( QStringLiteral(
"SrcRect" ) );
780 srcRectElem.setAttribute( QStringLiteral(
"xOff" ), QStringLiteral(
"0" ) );
781 srcRectElem.setAttribute( QStringLiteral(
"yOff" ), QStringLiteral(
"0" ) );
782 srcRectElem.setAttribute( QStringLiteral(
"xSize" ), xSize );
783 srcRectElem.setAttribute( QStringLiteral(
"ySize" ), ySize );
784 simpleSourceElem.appendChild( srcRectElem );
787 QDomElement dstRectElem = mVRTDocument.createElement( QStringLiteral(
"DstRect" ) );
788 dstRectElem.setAttribute( QStringLiteral(
"xOff" ), xOffset );
789 dstRectElem.setAttribute( QStringLiteral(
"yOff" ), yOffset );
790 dstRectElem.setAttribute( QStringLiteral(
"xSize" ), xSize );
791 dstRectElem.setAttribute( QStringLiteral(
"ySize" ), ySize );
792 simpleSourceElem.appendChild( dstRectElem );
794 bandElem.appendChild( simpleSourceElem );
797 void QgsRasterFileWriter::buildPyramids(
const QString &filename,
QgsRasterDataProvider *destProviderIn )
805 destProvider = qobject_cast< QgsRasterDataProvider * >(
QgsProviderRegistry::instance()->createProvider( mOutputProviderKey, filename, providerOptions ) );
806 if ( !destProvider || !destProvider->
isValid() )
816 QList< QgsRasterPyramid> myPyramidList;
817 if ( ! mPyramidsList.isEmpty() )
819 for (
int myCounterInt = 0; myCounterInt < myPyramidList.count(); myCounterInt++ )
821 myPyramidList[myCounterInt].setBuild(
true );
824 QgsDebugMsgLevel( QStringLiteral(
"building pyramids : %1 pyramids, %2 resampling, %3 format, %4 options" ).arg( myPyramidList.count() ).arg( mPyramidsResampling ).arg( mPyramidsFormat ).arg( mPyramidsConfigOptions.count() ), 4 );
826 QString res = destProvider->
buildPyramids( myPyramidList, mPyramidsResampling,
827 mPyramidsFormat, mPyramidsConfigOptions );
833 QString title, message;
834 if ( res == QLatin1String(
"ERROR_WRITE_ACCESS" ) )
836 title = QObject::tr(
"Building Pyramids" );
837 message = QObject::tr(
"Write access denied. Adjust the file permissions and try again." );
839 else if ( res == QLatin1String(
"ERROR_WRITE_FORMAT" ) )
841 title = QObject::tr(
"Building Pyramids" );
842 message = QObject::tr(
"The file was not writable. Some formats do not "
843 "support pyramid overviews. Consult the GDAL documentation if in doubt." );
845 else if ( res == QLatin1String(
"FAILED_NOT_SUPPORTED" ) )
847 title = QObject::tr(
"Building Pyramids" );
848 message = QObject::tr(
"Building pyramid overviews is not supported on this type of raster." );
850 else if ( res == QLatin1String(
"ERROR_VIRTUAL" ) )
852 title = QObject::tr(
"Building Pyramids" );
853 message = QObject::tr(
"Building pyramid overviews is not supported on this type of raster." );
855 QMessageBox::warning(
nullptr, title, message );
858 if ( !destProviderIn )
863 int QgsRasterFileWriter::pyramidsProgress(
double dfComplete,
const char *pszMessage,
void *pData )
865 Q_UNUSED( pszMessage )
866 GDALTermProgress( dfComplete, 0, 0 );
867 QProgressDialog *progressDialog =
static_cast<QProgressDialog *
>( pData );
868 if ( pData && progressDialog->wasCanceled() )
875 progressDialog->setRange( 0, 100 );
876 progressDialog->setValue( dfComplete * 100 );
882 void QgsRasterFileWriter::createVRT(
int xSize,
int ySize,
const QgsCoordinateReferenceSystem &
crs,
double *geoTransform,
Qgis::DataType type,
const QList<bool> &destHasNoDataValueList,
const QList<double> &destNoDataValueList )
884 mVRTDocument.clear();
885 QDomElement VRTDatasetElem = mVRTDocument.createElement( QStringLiteral(
"VRTDataset" ) );
888 VRTDatasetElem.setAttribute( QStringLiteral(
"rasterXSize" ), xSize );
889 VRTDatasetElem.setAttribute( QStringLiteral(
"rasterYSize" ), ySize );
890 mVRTDocument.appendChild( VRTDatasetElem );
893 QDomElement SRSElem = mVRTDocument.createElement( QStringLiteral(
"SRS" ) );
894 QDomText crsText = mVRTDocument.createTextNode(
crs.
toWkt() );
895 SRSElem.appendChild( crsText );
896 VRTDatasetElem.appendChild( SRSElem );
901 QDomElement geoTransformElem = mVRTDocument.createElement( QStringLiteral(
"GeoTransform" ) );
902 QString geoTransformString = QString::number( geoTransform[0],
'f', 6 ) +
", " + QString::number( geoTransform[1] ) +
", " + QString::number( geoTransform[2] ) +
903 ", " + QString::number( geoTransform[3],
'f', 6 ) +
", " + QString::number( geoTransform[4] ) +
", " + QString::number( geoTransform[5] );
904 QDomText geoTransformText = mVRTDocument.createTextNode( geoTransformString );
905 geoTransformElem.appendChild( geoTransformText );
906 VRTDatasetElem.appendChild( geoTransformElem );
919 QStringList colorInterp;
920 colorInterp << QStringLiteral(
"Red" ) << QStringLiteral(
"Green" ) << QStringLiteral(
"Blue" ) << QStringLiteral(
"Alpha" );
922 QMap<Qgis::DataType, QString> dataTypes;
934 for (
int i = 1; i <= nBands; i++ )
936 QDomElement VRTBand = mVRTDocument.createElement( QStringLiteral(
"VRTRasterBand" ) );
938 VRTBand.setAttribute( QStringLiteral(
"band" ), QString::number( i ) );
939 QString dataType = dataTypes.value( type );
940 VRTBand.setAttribute( QStringLiteral(
"dataType" ), dataType );
942 if ( mMode ==
Image )
944 VRTBand.setAttribute( QStringLiteral(
"dataType" ), QStringLiteral(
"Byte" ) );
945 QDomElement colorInterpElement = mVRTDocument.createElement( QStringLiteral(
"ColorInterp" ) );
946 QDomText interpText = mVRTDocument.createTextNode( colorInterp.value( i - 1 ) );
947 colorInterpElement.appendChild( interpText );
948 VRTBand.appendChild( colorInterpElement );
951 if ( !destHasNoDataValueList.isEmpty() && destHasNoDataValueList.value( i - 1 ) )
953 VRTBand.setAttribute( QStringLiteral(
"NoDataValue" ), QString::number( destNoDataValueList.value( i - 1 ) ) );
956 mVRTBands.append( VRTBand );
957 VRTDatasetElem.appendChild( VRTBand );
961 bool QgsRasterFileWriter::writeVRT(
const QString &file )
963 QFile outputFile( file );
964 if ( ! outputFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
969 QTextStream outStream( &outputFile );
970 mVRTDocument.save( outStream, 2 );
975 int iterRows,
int iterLeft,
int iterTop,
const QString &outputUrl,
int fileIndex,
int nBands,
Qgis::DataType type,
978 double mup = extent.
width() / nCols;
979 double mapLeft = extent.
xMinimum() + iterLeft * mup;
980 double mapRight = mapLeft + mup * iterCols;
981 double mapTop = extent.
yMaximum() - iterTop * mup;
982 double mapBottom = mapTop - iterRows * mup;
983 QgsRectangle mapRect( mapLeft, mapBottom, mapRight, mapTop );
985 QString outputFile =
outputUrl +
'/' + partFileName( fileIndex );
988 double geoTransform[6];
989 geoTransform[0] = mapRect.xMinimum();
990 geoTransform[1] = mup;
991 geoTransform[2] = 0.0;
992 geoTransform[3] = mapRect.yMaximum();
993 geoTransform[4] = 0.0;
994 geoTransform[5] = -mup;
1001 return destProvider;
1006 const QList<bool> &destHasNoDataValueList,
const QList<double> &destNoDataValueList )
1010 createVRT( nCols, nRows,
crs, geoTransform, type, destHasNoDataValueList, destNoDataValueList );
1018 if ( mBuildPyramidsFlag == -4 && mOutputProviderKey ==
"gdal" && mOutputFormat.compare( QLatin1String(
"gtiff" ), Qt::CaseInsensitive ) == 0 )
1019 mCreateOptions <<
"COPY_SRC_OVERVIEWS=YES";
1024 if ( !destProvider )
1026 QgsDebugMsg( QStringLiteral(
"No provider created" ) );
1029 return destProvider;
1033 void QgsRasterFileWriter::globalOutputParameters(
const QgsRectangle &extent,
int nCols,
int &nRows,
1034 double *geoTransform,
double &pixelSize )
1036 pixelSize = extent.
width() / nCols;
1041 nRows =
static_cast< double >( nCols ) / extent.
width() * extent.
height() + 0.5;
1043 geoTransform[0] = extent.
xMinimum();
1044 geoTransform[1] = pixelSize;
1045 geoTransform[2] = 0.0;
1046 geoTransform[3] = extent.
yMaximum();
1047 geoTransform[4] = 0.0;
1048 geoTransform[5] = -( extent.
height() / nRows );
1051 QString QgsRasterFileWriter::partFileName(
int fileIndex )
1054 QFileInfo outputInfo( mOutputUrl );
1055 return QStringLiteral(
"%1.%2.tif" ).arg( outputInfo.fileName() ).arg( fileIndex );
1058 QString QgsRasterFileWriter::vrtFileName()
1060 QFileInfo outputInfo( mOutputUrl );
1061 return QStringLiteral(
"%1.vrt" ).arg( outputInfo.fileName() );
1066 QString ext = extension.trimmed();
1067 if ( ext.isEmpty() )
1070 if ( ext.startsWith(
'.' ) )
1074 int const drvCount = GDALGetDriverCount();
1076 for (
int i = 0; i < drvCount; ++i )
1078 GDALDriverH drv = GDALGetDriver( i );
1081 char **driverMetadata = GDALGetMetadata( drv,
nullptr );
1082 if ( CSLFetchBoolean( driverMetadata, GDAL_DCAP_RASTER,
false ) )
1084 QString drvName = GDALGetDriverShortName( drv );
1085 QStringList driverExtensions = QString( GDALGetMetadataItem( drv, GDAL_DMD_EXTENSIONS,
nullptr ) ).split(
' ' );
1087 const auto constDriverExtensions = driverExtensions;
1088 for (
const QString &driver : constDriverExtensions )
1090 if ( driver.compare( ext, Qt::CaseInsensitive ) == 0 )
1101 GDALDriverH drv = GDALGetDriverByName( format.toLocal8Bit().data() );
1104 char **driverMetadata = GDALGetMetadata( drv,
nullptr );
1105 if ( CSLFetchBoolean( driverMetadata, GDAL_DCAP_RASTER,
false ) )
1107 return QString( GDALGetMetadataItem( drv, GDAL_DMD_EXTENSIONS,
nullptr ) ).split(
' ' );
1110 return QStringList();
1115 GDALDriverH drv = GDALGetDriverByName( driverName.toLocal8Bit().data() );
1118 QString drvName = GDALGetDriverLongName( drv );
1119 QString extensionsString = QString( GDALGetMetadataItem( drv, GDAL_DMD_EXTENSIONS,
nullptr ) );
1120 if ( extensionsString.isEmpty() )
1124 QStringList extensions = extensionsString.split(
' ' );
1125 QString filter = drvName +
" (";
1126 for (
const QString &ext : extensions )
1128 filter.append( QStringLiteral(
"*.%1 *.%2 " ).arg( ext.toLower(), ext.toUpper() ) );
1130 filter = filter.trimmed().append( QStringLiteral(
")" ) );
1139 static QReadWriteLock sFilterLock;
1140 static QMap< RasterFormatOptions, QList< QgsRasterFileWriter::FilterFormatDetails > > sFilters;
1144 const auto it = sFilters.constFind( options );
1145 if ( it != sFilters.constEnd() )
1149 int const drvCount = GDALGetDriverCount();
1152 QList< QgsRasterFileWriter::FilterFormatDetails > results;
1156 for (
int i = 0; i < drvCount; ++i )
1158 GDALDriverH drv = GDALGetDriver( i );
1163 QString drvName = GDALGetDriverShortName( drv );
1165 if ( filterString.isEmpty() )
1174 if ( drvName == QLatin1String(
"GTiff" ) )
1176 tifFormat = details;
1188 return a.driverName < b.driverName;
1195 results.insert( 0, tifFormat );
1199 sFilters.insert( options, results );
1207 QStringList extensions;
1209 QRegularExpression rx( QStringLiteral(
"\\*\\.([a-zA-Z0-9]*)" ) );
1213 QString ext = format.filterString;
1214 QRegularExpressionMatch match = rx.match( ext );
1215 if ( !match.hasMatch() )
1218 QString matched = match.captured( 1 );
1219 extensions << matched;
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.
@ UInt16
Sixteen bit unsigned integer (quint16)
@ Byte
Eight bit unsigned integer (quint8)
@ ARGB32
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32.
@ Float64
Sixty four bit floating point (double)
@ CFloat32
Complex Float32.
@ UInt32
Thirty two bit unsigned integer (quint32)
static double maximumValuePossible(Qgis::DataType dataType)
Helper function that returns the maximum possible value for a data type.
static double minimumValuePossible(Qgis::DataType dataType)
Helper function that returns the minimum possible value for a data type.
This class represents a coordinate reference system (CRS).
QString toWkt(WktVariant variant=WKT1_GDAL, bool multiline=false, int indentationWidth=4) const
Returns a WKT representation of this CRS.
Contains information about the context in which a coordinate transform is executed.
QgsCoordinateTransformContext transformContext() const
Returns data provider coordinate transform context.
virtual bool isValid() const =0
Returns true if this is a valid layer.
virtual QgsError error() const
Gets current status error.
bool isEmpty() const
Test if any error is set.
QString summary() const
Short error description, usually the first error in chain, the real error.
bool isCanceled() const SIP_HOLDGIL
Tells whether the operation has been canceled already.
void setProgress(double progress)
Sets the current progress for the feedback object.
static bool supportsRasterCreate(GDALDriverH driver)
Reads whether a driver supports GDALCreate() for raster purposes.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
The RasterBandStats struct is a container for statistics about a single raster band.
double minimumValue
The minimum cell value in the raster band.
double maximumValue
The maximum cell value in the raster band.
Feedback object tailored for raster block reading.
void appendError(const QString &error)
Appends an error message to the stored list of errors.
static int typeSize(Qgis::DataType dataType) SIP_HOLDGIL
Returns the size in bytes for the specified dataType.
static Qgis::DataType typeWithNoDataValue(Qgis::DataType dataType, double *noDataValue)
For given data type returns wider type and sets no data value.
static bool typeIsColor(Qgis::DataType type)
Returns true if data type is color.
Base class for raster data providers.
virtual QString buildPyramids(const QList< QgsRasterPyramid > &pyramidList, const QString &resamplingMethod="NEAREST", QgsRaster::RasterPyramidsFormat format=QgsRaster::PyramidsGTiff, const QStringList &configOptions=QStringList(), QgsRasterBlockFeedback *feedback=nullptr)
Creates pyramid overviews.
virtual bool sourceHasNoDataValue(int bandNo) const
Returns true if source band has no data value.
virtual bool setNoDataValue(int bandNo, double noDataValue)
Set no data value on created dataset.
virtual QList< QgsRasterPyramid > buildPyramidList(const QList< int > &overviewList=QList< int >())
Returns the raster layers pyramid list.
Qgis::DataType sourceDataType(int bandNo) const override=0
Returns source data type for the band specified by number, source data type may be shorter than dataT...
virtual double sourceNoDataValue(int bandNo) const
Value representing no data value.
QgsRectangle extent() const override=0
Returns the extent of the layer.
Qgis::DataType dataType(int bandNo) const override=0
Returns data type for the band specified by number.
static QgsRasterDataProvider * create(const QString &providerKey, const QString &uri, const QString &format, int nBands, Qgis::DataType type, int width, int height, double *geoTransform, const QgsCoordinateReferenceSystem &crs, const QStringList &createOptions=QStringList())
Creates a new dataset with mDataSourceURI.
virtual bool write(void *data, int band, int width, int height, int xOffset, int yOffset)
Writes into the provider datasource.
Q_DECL_DEPRECATED WriterError writeRaster(const QgsRasterPipe *pipe, int nCols, int nRows, const QgsRectangle &outputExtent, const QgsCoordinateReferenceSystem &crs, QgsRasterBlockFeedback *feedback=nullptr)
Write raster file.
static QStringList extensionsForFormat(const QString &format)
Returns a list of known file extensions for the given GDAL driver format.
static QString filterForDriver(const QString &driverName)
Creates a filter for an GDAL driver key.
static QString driverForExtension(const QString &extension)
Returns the GDAL driver name for a specified file extension.
QgsRasterFileWriter(const QString &outputUrl)
static QStringList supportedFormatExtensions(RasterFormatOptions options=SortRecommended)
Returns a list of file extensions for supported formats.
QgsRasterDataProvider * createMultiBandRaster(Qgis::DataType dataType, int width, int height, const QgsRectangle &extent, const QgsCoordinateReferenceSystem &crs, int nBands)
Create a raster file with given number of bands without initializing the pixel data.
QString outputUrl() const
Returns the output URL for the raster.
@ WriteCanceled
Writing was manually canceled.
@ NoDataConflict
Internal error if a value used for 'no data' was found in input.
QgsRasterDataProvider * createOneBandRaster(Qgis::DataType dataType, int width, int height, const QgsRectangle &extent, const QgsCoordinateReferenceSystem &crs)
Create a raster file with one band without initializing the pixel data.
@ SortRecommended
Use recommended sort order, with extremely commonly used formats listed first.
static QList< QgsRasterFileWriter::FilterFormatDetails > supportedFiltersAndFormats(RasterFormatOptions options=SortRecommended)
Returns a list or pairs, with format filter string as first element and GDAL format key as second ele...
Base class for processing filters like renderers, reprojector, resampler etc.
virtual Qgis::DataType dataType(int bandNo) const =0
Returns data type for the band specified by number.
virtual int xSize() const
Gets raster size.
virtual const QgsRasterInterface * sourceInput() const
Gets source / raw input, the first in pipe, usually provider.
virtual int bandCount() const =0
Gets number of bands.
virtual QgsRasterBandStats bandStatistics(int bandNo, int stats=QgsRasterBandStats::All, const QgsRectangle &extent=QgsRectangle(), int sampleSize=0, QgsRasterBlockFeedback *feedback=nullptr)
Returns the band statistics.
virtual int ySize() const
Iterator for sequentially processing raster cells.
const QgsRasterInterface * input() const
Returns the input raster interface which is being iterated over.
int maximumTileWidth() const
Returns the maximum tile width returned during iteration.
void setMaximumTileWidth(int w)
Sets the maximum tile width returned during iteration.
bool readNextRasterPart(int bandNumber, int &nCols, int &nRows, QgsRasterBlock **block, int &topLeftCol, int &topLeftRow)
Fetches next part of raster data, caller takes ownership of the block and caller should delete the bl...
int maximumTileHeight() const
Returns the minimum tile width returned during iteration.
void startRasterRead(int bandNumber, qgssize nCols, qgssize nRows, const QgsRectangle &extent, QgsRasterBlockFeedback *feedback=nullptr)
Start reading of raster band.
void setMaximumTileHeight(int h)
Sets the minimum tile height returned during iteration.
Raster pipe that deals with null values.
void setOutputNoDataValue(int bandNo, double noData)
Sets the output no data value.
QgsRasterRangeList noData(int bandNo) const
Base class for processing modules.
QgsRasterDataProvider * provider() const
QgsRasterProjector * projector() const
QgsRasterInterface * last() const
QgsRasterNuller * nuller() const
QgsRasterProjector implements approximate projection support for it calculates grid of points in sour...
QgsCoordinateReferenceSystem destinationCrs() const
Returns the destination CRS.
QgsCoordinateReferenceSystem sourceCrs() const
Returns the source CRS.
The QgsReadWriteLocker class is a convenience class that simplifies locking and unlocking QReadWriteL...
void changeMode(Mode mode)
Change the mode of the lock to mode.
A rectangle specified with double values.
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
double height() const SIP_HOLDGIL
Returns the height of the rectangle.
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
QString qgsEnumValueToKey(const T &value)
Returns the value for the given key of an enum.
unsigned long long qgssize
Qgssize is used instead of size_t, because size_t is stdlib type, unknown by SIP, and it would be har...
#define QgsDebugMsgLevel(str, level)
const QgsCoordinateReferenceSystem & crs
Setting options for creating vector data providers.