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 )
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() )
604 if ( feedback && !destProvider->error().isEmpty() )
606 feedback->
appendError( destProvider->error().summary() );
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" ) );
628 if (
Qgis::Byte != destProvider->dataType( 1 ) )
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 )
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;
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;
virtual int bandCount() const =0
Gets number of bands.
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.
A rectangle specified with double values.
QgsRasterFileWriter(const QString &outputUrl)
Base class for processing modules.
Iterator for sequentially processing raster cells.
Writing was manually canceled.
static double minimumValuePossible(Qgis::DataType dataType)
Helper function that returns the minimum possible value for a GDAL data type.
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.
static QString filterForDriver(const QString &driverName)
Creates a filter for an GDAL driver key.
static double maximumValuePossible(Qgis::DataType dataType)
Helper function that returns the maximum possible value for a GDAL data type.
void setProgress(double progress)
Sets the current progress for the feedback object.
QgsRasterProjector * projector() const
Raster pipe that deals with null values.
Thirty two bit unsigned integer (quint32)
DataType
Raster data types.
QgsRasterInterface * last() const
double maximumValue
The maximum cell value in the raster band.
static QStringList extensionsForFormat(const QString &format)
Returns a list of known file extensions for the given GDAL driver format.
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 bool setNoDataValue(int bandNo, double noDataValue)
Set no data value on created dataset.
virtual Qgis::DataType dataType(int bandNo) const =0
Returns data type for the band specified by number.
Thirty two bit floating point (float)
const QgsCoordinateReferenceSystem & crs
virtual QString buildPyramids(const QList< QgsRasterPyramid > &pyramidList, const QString &resamplingMethod="NEAREST", QgsRaster::RasterPyramidsFormat format=QgsRaster::PyramidsGTiff, const QStringList &configOptions=QStringList(), QgsRasterBlockFeedback *feedback=nullptr)
Create pyramid overviews.
static bool supportsRasterCreate(GDALDriverH driver)
Reads whether a driver supports GDALCreate() for raster purposes.
Sixteen bit signed integer (qint16)
virtual double sourceNoDataValue(int bandNo) const
Value representing no data value.
Sixty four bit floating point (double)
QgsDataProvider * createProvider(const QString &providerKey, const QString &dataSource, const QgsDataProvider::ProviderOptions &options=QgsDataProvider::ProviderOptions())
Creates a new instance of a provider.
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
static QString driverForExtension(const QString &extension)
Returns the GDAL driver name for a specified file extension.
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32_Premultiplied.
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.
The RasterBandStats struct is a container for statistics about a single raster band.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
static QStringList supportedFormatExtensions(RasterFormatOptions options=SortRecommended)
Returns a list of file extensions for supported formats.
QgsCoordinateReferenceSystem sourceCrs() const
Returns the source CRS.
#define QgsDebugMsgLevel(str, level)
virtual QList< QgsRasterPyramid > buildPyramidList(QList< int > overviewList=QList< int >())
Returns the raster layers pyramid list.
QgsRectangle extent() const override=0
Returns the extent of the layer.
virtual bool isValid() const =0
Returns true if this is a valid layer.
void startRasterRead(int bandNumber, qgssize nCols, qgssize nRows, const QgsRectangle &extent, QgsRasterBlockFeedback *feedback=nullptr)
Start reading of raster band.
double width() const
Returns the width of the rectangle.
void appendError(const QString &error)
Appends an error message to the stored list of errors.
static int typeSize(int dataType)
Sixteen bit unsigned integer (quint16)
Q_DECL_DEPRECATED WriterError writeRaster(const QgsRasterPipe *pipe, int nCols, int nRows, const QgsRectangle &outputExtent, const QgsCoordinateReferenceSystem &crs, QgsRasterBlockFeedback *feedback=nullptr)
Write raster file.
QgsRasterRangeList noData(int bandNo) const
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...
Contains information about the context in which a coordinate transform is executed.
Base class for processing filters like renderers, reprojector, resampler etc.
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...
virtual bool sourceHasNoDataValue(int bandNo) const
Returns true if source band has no data value.
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...
void setOutputNoDataValue(int bandNo, double noData)
Sets the output no data value.
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
double xMaximum() const
Returns the x maximum value (right side of rectangle).
QgsRasterProjector implements approximate projection support for it calculates grid of points in sour...
QgsCoordinateTransformContext transformContext() const
Returns data provider coordinate transform context.
virtual QgsRasterBandStats bandStatistics(int bandNo, int stats=QgsRasterBandStats::All, const QgsRectangle &extent=QgsRectangle(), int sampleSize=0, QgsRasterBlockFeedback *feedback=nullptr)
Returns the band statistics.
void setMaximumTileWidth(int w)
Sets the maximum tile width returned during iteration.
QgsCoordinateReferenceSystem destinationCrs() const
Returns the destination CRS.
Setting options for creating vector data providers.
void setMaximumTileHeight(int h)
Sets the minimum tile height returned during iteration.
Internal error if a value used for 'no data' was found in input.
const QgsRasterInterface * input() const
Returns the input raster interface which is being iterated over.
int maximumTileHeight() const
Returns the minimum tile width returned during iteration.
bool isCanceled() const
Tells whether the operation has been canceled already.
This class represents a coordinate reference system (CRS).
Use recommended sort order, with extremely commonly used formats listed first.
QgsRasterDataProvider * provider() const
double xMinimum() const
Returns the x minimum value (left side of rectangle).
double minimumValue
The minimum cell value in the raster band.
QgsRasterNuller * nuller() const
double yMaximum() const
Returns the y maximum value (top side of rectangle).
virtual bool write(void *data, int band, int width, int height, int xOffset, int yOffset)
Writes into the provider datasource.
Feedback object tailored for raster block reading.
QString outputUrl() const
Returns the output URL for the raster.
Eight bit unsigned integer (quint8)
Qgis::DataType dataType(int bandNo) const override=0
Returns data type for the band specified by number.
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32.
virtual const QgsRasterInterface * sourceInput() const
Gets source / raw input, the first in pipe, usually provider.
QString toWkt(WktVariant variant=WKT1_GDAL, bool multiline=false, int indentationWidth=4) const
Returns a WKT representation of this CRS.
int maximumTileWidth() const
Returns the maximum tile width returned during iteration.
double height() const
Returns the height of the rectangle.
Base class for raster data providers.
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.