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 ( !partDestProvider->write( destBlockList[i - 1]->bits( 0 ), i, iterCols, iterRows, 0, 0 ) )
530 addToVRT( partFileName( fileIndex ), i, iterCols, iterRows, iterLeft, iterTop );
534 else if ( destProvider )
537 for (
int i = 1; i <= nBands; ++i )
539 if ( !destProvider->
write( destBlockList[i - 1]->bits( 0 ), i, iterCols, iterRows, iterLeft, iterTop ) )
575 const size_t nMaxPixels =
static_cast<size_t>( mMaxTileWidth ) * mMaxTileHeight;
576 std::vector<unsigned char> redData( nMaxPixels );
577 std::vector<unsigned char> greenData( nMaxPixels );
578 std::vector<unsigned char> blueData( nMaxPixels );
579 std::vector<unsigned char> alphaData( nMaxPixels );
580 int iterLeft = 0, iterTop = 0, iterCols = 0, iterRows = 0;
585 double geoTransform[6];
586 globalOutputParameters( outputExtent, nCols, nRows, geoTransform, pixelSize );
588 const int nOutputBands = 4;
589 std::unique_ptr< QgsRasterDataProvider > destProvider( initOutput( nCols, nRows, crs, geoTransform, nOutputBands,
Qgis::Byte ) );
596 if ( !destProvider->isValid() )
598 if ( feedback && !destProvider->error().isEmpty() )
600 feedback->
appendError( destProvider->error().summary() );
604 if ( nCols != destProvider->xSize() || nRows != destProvider->ySize() )
606 QgsDebugMsg( QStringLiteral(
"Created raster does not have requested dimensions" ) );
609 feedback->
appendError( QObject::tr(
"Created raster does not have requested dimensions" ) );
613 if ( nOutputBands != destProvider->bandCount() )
615 QgsDebugMsg( QStringLiteral(
"Created raster does not have requested band count" ) );
618 feedback->
appendError( QObject::tr(
"Created raster does not have requested band count" ) );
622 if (
Qgis::Byte != destProvider->dataType( 1 ) )
624 QgsDebugMsg( QStringLiteral(
"Created raster does not have requested data type" ) );
627 feedback->
appendError( QObject::tr(
"Created raster does not have requested data type" ) );
640 nParts = nPartsX * nPartsY;
643 std::unique_ptr< QgsRasterBlock > inputBlock;
644 while ( iter->
readNextRasterPart( 1, iterCols, iterRows, inputBlock, iterLeft, iterTop ) )
651 if ( feedback && fileIndex < ( nParts - 1 ) )
653 feedback->
setProgress( 100.0 * fileIndex / static_cast< double >( nParts ) );
662 for (
qgssize i = 0; i < nPixels; ++i )
664 QRgb
c = inputBlock->color( i );
665 if ( isPremultiplied )
667 c = qUnpremultiply( c );
669 redData[i] =
static_cast<unsigned char>( qRed( c ) );
670 greenData[i] =
static_cast<unsigned char>( qGreen( c ) );
671 blueData[i] =
static_cast<unsigned char>( qBlue( c ) );
672 alphaData[i] =
static_cast<unsigned char>( qAlpha( c ) );
678 std::unique_ptr< QgsRasterDataProvider > partDestProvider( createPartProvider( outputExtent,
679 nCols, iterCols, iterRows,
680 iterLeft, iterTop, mOutputUrl, fileIndex,
683 if ( !partDestProvider || partDestProvider->isValid() )
689 if ( !partDestProvider->write( &redData[0], 1, iterCols, iterRows, 0, 0 ) ||
690 !partDestProvider->write( &greenData[0], 2, iterCols, iterRows, 0, 0 ) ||
691 !partDestProvider->write( &blueData[0], 3, iterCols, iterRows, 0, 0 ) ||
692 !partDestProvider->write( &alphaData[0], 4, iterCols, iterRows, 0, 0 ) )
697 addToVRT( partFileName( fileIndex ), 1, iterCols, iterRows, iterLeft, iterTop );
698 addToVRT( partFileName( fileIndex ), 2, iterCols, iterRows, iterLeft, iterTop );
699 addToVRT( partFileName( fileIndex ), 3, iterCols, iterRows, iterLeft, iterTop );
700 addToVRT( partFileName( fileIndex ), 4, iterCols, iterRows, iterLeft, iterTop );
702 else if ( destProvider )
704 if ( !destProvider->write( &redData[0], 1, iterCols, iterRows, iterLeft, iterTop ) ||
705 !destProvider->write( &greenData[0], 2, iterCols, iterRows, iterLeft, iterTop ) ||
706 !destProvider->write( &blueData[0], 3, iterCols, iterRows, iterLeft, iterTop ) ||
707 !destProvider->write( &alphaData[0], 4, iterCols, iterRows, iterLeft, iterTop ) )
715 destProvider.reset();
724 QString vrtFilePath( mOutputUrl +
'/' + vrtFileName() );
725 writeVRT( vrtFilePath );
728 buildPyramids( vrtFilePath );
735 buildPyramids( mOutputUrl );
741 void QgsRasterFileWriter::addToVRT(
const QString &filename,
int band,
int xSize,
int ySize,
int xOffset,
int yOffset )
743 QDomElement bandElem = mVRTBands.value( band - 1 );
745 QDomElement simpleSourceElem = mVRTDocument.createElement( QStringLiteral(
"SimpleSource" ) );
748 QDomElement sourceFilenameElem = mVRTDocument.createElement( QStringLiteral(
"SourceFilename" ) );
749 sourceFilenameElem.setAttribute( QStringLiteral(
"relativeToVRT" ), QStringLiteral(
"1" ) );
750 QDomText sourceFilenameText = mVRTDocument.createTextNode( filename );
751 sourceFilenameElem.appendChild( sourceFilenameText );
752 simpleSourceElem.appendChild( sourceFilenameElem );
755 QDomElement sourceBandElem = mVRTDocument.createElement( QStringLiteral(
"SourceBand" ) );
756 QDomText sourceBandText = mVRTDocument.createTextNode( QString::number( band ) );
757 sourceBandElem.appendChild( sourceBandText );
758 simpleSourceElem.appendChild( sourceBandElem );
761 QDomElement sourcePropertiesElem = mVRTDocument.createElement( QStringLiteral(
"SourceProperties" ) );
762 sourcePropertiesElem.setAttribute( QStringLiteral(
"RasterXSize" ), xSize );
763 sourcePropertiesElem.setAttribute( QStringLiteral(
"RasterYSize" ), ySize );
764 sourcePropertiesElem.setAttribute( QStringLiteral(
"BlockXSize" ), xSize );
765 sourcePropertiesElem.setAttribute( QStringLiteral(
"BlockYSize" ), ySize );
766 sourcePropertiesElem.setAttribute( QStringLiteral(
"DataType" ), QStringLiteral(
"Byte" ) );
767 simpleSourceElem.appendChild( sourcePropertiesElem );
770 QDomElement srcRectElem = mVRTDocument.createElement( QStringLiteral(
"SrcRect" ) );
771 srcRectElem.setAttribute( QStringLiteral(
"xOff" ), QStringLiteral(
"0" ) );
772 srcRectElem.setAttribute( QStringLiteral(
"yOff" ), QStringLiteral(
"0" ) );
773 srcRectElem.setAttribute( QStringLiteral(
"xSize" ), xSize );
774 srcRectElem.setAttribute( QStringLiteral(
"ySize" ), ySize );
775 simpleSourceElem.appendChild( srcRectElem );
778 QDomElement dstRectElem = mVRTDocument.createElement( QStringLiteral(
"DstRect" ) );
779 dstRectElem.setAttribute( QStringLiteral(
"xOff" ), xOffset );
780 dstRectElem.setAttribute( QStringLiteral(
"yOff" ), yOffset );
781 dstRectElem.setAttribute( QStringLiteral(
"xSize" ), xSize );
782 dstRectElem.setAttribute( QStringLiteral(
"ySize" ), ySize );
783 simpleSourceElem.appendChild( dstRectElem );
785 bandElem.appendChild( simpleSourceElem );
788 void QgsRasterFileWriter::buildPyramids(
const QString &filename,
QgsRasterDataProvider *destProviderIn )
797 if ( !destProvider || !destProvider->
isValid() )
807 QList< QgsRasterPyramid> myPyramidList;
808 if ( ! mPyramidsList.isEmpty() )
810 for (
int myCounterInt = 0; myCounterInt < myPyramidList.count(); myCounterInt++ )
812 myPyramidList[myCounterInt].build =
true;
815 QgsDebugMsgLevel( QStringLiteral(
"building pyramids : %1 pyramids, %2 resampling, %3 format, %4 options" ).arg( myPyramidList.count() ).arg( mPyramidsResampling ).arg( mPyramidsFormat ).arg( mPyramidsConfigOptions.count() ), 4 );
817 QString res = destProvider->
buildPyramids( myPyramidList, mPyramidsResampling,
818 mPyramidsFormat, mPyramidsConfigOptions );
824 QString title, message;
825 if ( res == QLatin1String(
"ERROR_WRITE_ACCESS" ) )
827 title = QObject::tr(
"Building Pyramids" );
828 message = QObject::tr(
"Write access denied. Adjust the file permissions and try again." );
830 else if ( res == QLatin1String(
"ERROR_WRITE_FORMAT" ) )
832 title = QObject::tr(
"Building Pyramids" );
833 message = QObject::tr(
"The file was not writable. Some formats do not " 834 "support pyramid overviews. Consult the GDAL documentation if in doubt." );
836 else if ( res == QLatin1String(
"FAILED_NOT_SUPPORTED" ) )
838 title = QObject::tr(
"Building Pyramids" );
839 message = QObject::tr(
"Building pyramid overviews is not supported on this type of raster." );
841 else if ( res == QLatin1String(
"ERROR_VIRTUAL" ) )
843 title = QObject::tr(
"Building Pyramids" );
844 message = QObject::tr(
"Building pyramid overviews is not supported on this type of raster." );
846 QMessageBox::warning(
nullptr, title, message );
849 if ( !destProviderIn )
854 int QgsRasterFileWriter::pyramidsProgress(
double dfComplete,
const char *pszMessage,
void *pData )
856 Q_UNUSED( pszMessage )
857 GDALTermProgress( dfComplete, 0, 0 );
858 QProgressDialog *progressDialog =
static_cast<QProgressDialog *
>( pData );
859 if ( pData && progressDialog->wasCanceled() )
866 progressDialog->setRange( 0, 100 );
867 progressDialog->setValue( dfComplete * 100 );
873 void QgsRasterFileWriter::createVRT(
int xSize,
int ySize,
const QgsCoordinateReferenceSystem &crs,
double *geoTransform,
Qgis::DataType type,
const QList<bool> &destHasNoDataValueList,
const QList<double> &destNoDataValueList )
875 mVRTDocument.clear();
876 QDomElement VRTDatasetElem = mVRTDocument.createElement( QStringLiteral(
"VRTDataset" ) );
879 VRTDatasetElem.setAttribute( QStringLiteral(
"rasterXSize" ), xSize );
880 VRTDatasetElem.setAttribute( QStringLiteral(
"rasterYSize" ), ySize );
881 mVRTDocument.appendChild( VRTDatasetElem );
884 QDomElement SRSElem = mVRTDocument.createElement( QStringLiteral(
"SRS" ) );
885 QDomText crsText = mVRTDocument.createTextNode( crs.
toWkt() );
886 SRSElem.appendChild( crsText );
887 VRTDatasetElem.appendChild( SRSElem );
892 QDomElement geoTransformElem = mVRTDocument.createElement( QStringLiteral(
"GeoTransform" ) );
893 QString geoTransformString = QString::number( geoTransform[0],
'f', 6 ) +
", " + QString::number( geoTransform[1] ) +
", " + QString::number( geoTransform[2] ) +
894 ", " + QString::number( geoTransform[3],
'f', 6 ) +
", " + QString::number( geoTransform[4] ) +
", " + QString::number( geoTransform[5] );
895 QDomText geoTransformText = mVRTDocument.createTextNode( geoTransformString );
896 geoTransformElem.appendChild( geoTransformText );
897 VRTDatasetElem.appendChild( geoTransformElem );
910 QStringList colorInterp;
911 colorInterp << QStringLiteral(
"Red" ) << QStringLiteral(
"Green" ) << QStringLiteral(
"Blue" ) << QStringLiteral(
"Alpha" );
913 QMap<Qgis::DataType, QString> dataTypes;
914 dataTypes.insert(
Qgis::Byte, QStringLiteral(
"Byte" ) );
915 dataTypes.insert(
Qgis::UInt16, QStringLiteral(
"UInt16" ) );
916 dataTypes.insert(
Qgis::Int16, QStringLiteral(
"Int16" ) );
917 dataTypes.insert(
Qgis::UInt32, QStringLiteral(
"Int32" ) );
918 dataTypes.insert(
Qgis::Float32, QStringLiteral(
"Float32" ) );
919 dataTypes.insert(
Qgis::Float64, QStringLiteral(
"Float64" ) );
920 dataTypes.insert(
Qgis::CInt16, QStringLiteral(
"CInt16" ) );
921 dataTypes.insert(
Qgis::CInt32, QStringLiteral(
"CInt32" ) );
925 for (
int i = 1; i <= nBands; i++ )
927 QDomElement VRTBand = mVRTDocument.createElement( QStringLiteral(
"VRTRasterBand" ) );
929 VRTBand.setAttribute( QStringLiteral(
"band" ), QString::number( i ) );
930 QString dataType = dataTypes.value( type );
931 VRTBand.setAttribute( QStringLiteral(
"dataType" ), dataType );
933 if ( mMode ==
Image )
935 VRTBand.setAttribute( QStringLiteral(
"dataType" ), QStringLiteral(
"Byte" ) );
936 QDomElement colorInterpElement = mVRTDocument.createElement( QStringLiteral(
"ColorInterp" ) );
937 QDomText interpText = mVRTDocument.createTextNode( colorInterp.value( i - 1 ) );
938 colorInterpElement.appendChild( interpText );
939 VRTBand.appendChild( colorInterpElement );
942 if ( !destHasNoDataValueList.isEmpty() && destHasNoDataValueList.value( i - 1 ) )
944 VRTBand.setAttribute( QStringLiteral(
"NoDataValue" ), QString::number( destNoDataValueList.value( i - 1 ) ) );
947 mVRTBands.append( VRTBand );
948 VRTDatasetElem.appendChild( VRTBand );
952 bool QgsRasterFileWriter::writeVRT(
const QString &file )
954 QFile outputFile( file );
955 if ( ! outputFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
960 QTextStream outStream( &outputFile );
961 mVRTDocument.save( outStream, 2 );
966 int iterRows,
int iterLeft,
int iterTop,
const QString &
outputUrl,
int fileIndex,
int nBands,
Qgis::DataType type,
969 double mup = extent.
width() / nCols;
970 double mapLeft = extent.
xMinimum() + iterLeft * mup;
971 double mapRight = mapLeft + mup * iterCols;
972 double mapTop = extent.
yMaximum() - iterTop * mup;
973 double mapBottom = mapTop - iterRows * mup;
974 QgsRectangle mapRect( mapLeft, mapBottom, mapRight, mapTop );
976 QString outputFile =
outputUrl +
'/' + partFileName( fileIndex );
979 double geoTransform[6];
980 geoTransform[0] = mapRect.
xMinimum();
981 geoTransform[1] = mup;
982 geoTransform[2] = 0.0;
983 geoTransform[3] = mapRect.
yMaximum();
984 geoTransform[4] = 0.0;
985 geoTransform[5] = -mup;
997 const QList<bool> &destHasNoDataValueList,
const QList<double> &destNoDataValueList )
1001 createVRT( nCols, nRows, crs, geoTransform, type, destHasNoDataValueList, destNoDataValueList );
1009 if ( mBuildPyramidsFlag == -4 && mOutputProviderKey ==
"gdal" && mOutputFormat.compare( QLatin1String(
"gtiff" ), Qt::CaseInsensitive ) == 0 )
1010 mCreateOptions <<
"COPY_SRC_OVERVIEWS=YES";
1015 if ( !destProvider )
1017 QgsDebugMsg( QStringLiteral(
"No provider created" ) );
1020 return destProvider;
1024 void QgsRasterFileWriter::globalOutputParameters(
const QgsRectangle &extent,
int nCols,
int &nRows,
1025 double *geoTransform,
double &pixelSize )
1027 pixelSize = extent.
width() / nCols;
1032 nRows =
static_cast< double >( nCols ) / extent.
width() * extent.
height() + 0.5;
1034 geoTransform[0] = extent.
xMinimum();
1035 geoTransform[1] = pixelSize;
1036 geoTransform[2] = 0.0;
1037 geoTransform[3] = extent.
yMaximum();
1038 geoTransform[4] = 0.0;
1039 geoTransform[5] = -( extent.
height() / nRows );
1042 QString QgsRasterFileWriter::partFileName(
int fileIndex )
1045 QFileInfo outputInfo( mOutputUrl );
1046 return QStringLiteral(
"%1.%2.tif" ).arg( outputInfo.fileName() ).arg( fileIndex );
1049 QString QgsRasterFileWriter::vrtFileName()
1051 QFileInfo outputInfo( mOutputUrl );
1052 return QStringLiteral(
"%1.vrt" ).arg( outputInfo.fileName() );
1057 QString ext = extension.trimmed();
1058 if ( ext.isEmpty() )
1061 if ( ext.startsWith(
'.' ) )
1065 int const drvCount = GDALGetDriverCount();
1067 for (
int i = 0; i < drvCount; ++i )
1069 GDALDriverH drv = GDALGetDriver( i );
1072 char **driverMetadata = GDALGetMetadata( drv,
nullptr );
1073 if ( CSLFetchBoolean( driverMetadata, GDAL_DCAP_RASTER,
false ) )
1075 QString drvName = GDALGetDriverShortName( drv );
1076 QStringList driverExtensions = QString( GDALGetMetadataItem( drv, GDAL_DMD_EXTENSIONS,
nullptr ) ).split(
' ' );
1078 const auto constDriverExtensions = driverExtensions;
1079 for (
const QString &driver : constDriverExtensions )
1081 if ( driver.compare( ext, Qt::CaseInsensitive ) == 0 )
1092 GDALDriverH drv = GDALGetDriverByName( format.toLocal8Bit().data() );
1095 char **driverMetadata = GDALGetMetadata( drv,
nullptr );
1096 if ( CSLFetchBoolean( driverMetadata, GDAL_DCAP_RASTER,
false ) )
1098 return QString( GDALGetMetadataItem( drv, GDAL_DMD_EXTENSIONS,
nullptr ) ).split(
' ' );
1101 return QStringList();
1106 GDALDriverH drv = GDALGetDriverByName( driverName.toLocal8Bit().data() );
1109 QString drvName = GDALGetDriverLongName( drv );
1110 QString extensionsString = QString( GDALGetMetadataItem( drv, GDAL_DMD_EXTENSIONS,
nullptr ) );
1111 if ( extensionsString.isEmpty() )
1115 QStringList extensions = extensionsString.split(
' ' );
1116 QString filter = drvName +
" (";
1117 for (
const QString &ext : extensions )
1119 filter.append( QStringLiteral(
"*.%1 *.%2 " ).arg( ext.toLower(), ext.toUpper() ) );
1121 filter = filter.trimmed().append( QStringLiteral(
")" ) );
1130 QList< FilterFormatDetails > results;
1133 int const drvCount = GDALGetDriverCount();
1137 for (
int i = 0; i < drvCount; ++i )
1139 GDALDriverH drv = GDALGetDriver( i );
1144 QString drvName = GDALGetDriverShortName( drv );
1146 if ( filterString.isEmpty() )
1155 if ( drvName == QLatin1String(
"GTiff" ) )
1157 tifFormat = details;
1176 results.insert( 0, tifFormat );
1186 QStringList extensions;
1188 QRegularExpression rx( QStringLiteral(
"\\*\\.([a-zA-Z0-9]*)" ) );
1192 QString ext = format.filterString;
1193 QRegularExpressionMatch match = rx.match( ext );
1194 if ( !match.hasMatch() )
1197 QString matched = match.captured( 1 );
1198 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.
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.
void startRasterRead(int bandNumber, int nCols, int nRows, const QgsRectangle &extent, QgsRasterBlockFeedback *feedback=nullptr)
Start reading of raster band.
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.