30 #include <QCoreApplication> 
   31 #include <QProgressDialog> 
   32 #include <QTextStream> 
   33 #include <QMessageBox> 
   34 #include <QRegularExpression> 
   39 #include <cpl_string.h> 
   48   double geoTransform[6];
 
   49   globalOutputParameters( extent, width, height, geoTransform, pixelSize );
 
   51   return initOutput( width, height, 
crs, geoTransform, 1, dataType, QList<bool>(), QList<double>() );
 
   60   double geoTransform[6];
 
   61   globalOutputParameters( extent, width, height, geoTransform, pixelSize );
 
   63   return initOutput( width, height, 
crs, geoTransform, nBands, dataType, QList<bool>(), QList<double>() );
 
   67   : mOutputUrl( outputUrl )
 
   72 QgsRasterFileWriter::QgsRasterFileWriter()
 
  114   QgsDebugMsgLevel( QStringLiteral( 
"reading from %1" ).arg( 
typeid( *iface ).name() ), 4 );
 
  118     QgsDebugMsg( QStringLiteral( 
"iface->srcInput() == 0" ) );
 
  123   QgsDebugMsgLevel( QStringLiteral( 
"srcInput = %1" ).arg( 
typeid( srcInput ).name() ), 4 );
 
  126   mFeedback = feedback;
 
  133     const QFileInfo fileInfo( mOutputUrl );
 
  134     if ( !fileInfo.exists() )
 
  136       const QDir dir = fileInfo.dir();
 
  137       if ( !dir.mkdir( fileInfo.fileName() ) )
 
  139         QgsDebugMsg( 
"Cannot create output VRT directory " + fileInfo.fileName() + 
" in " + dir.absolutePath() );
 
  146   QFile pyramidFile( mOutputUrl + ( mTiledMode ? 
".vrt.ovr" : 
".ovr" ) );
 
  147   if ( pyramidFile.exists() )
 
  148     pyramidFile.remove();
 
  149   pyramidFile.setFileName( mOutputUrl + ( mTiledMode ? 
".vrt.rrd" : 
".rrd" ) );
 
  150   if ( pyramidFile.exists() )
 
  151     pyramidFile.remove();
 
  153   if ( mMode == 
Image )
 
  155     const WriterError e = writeImageRaster( &iter, nCols, nRows, outputExtent, 
crs, feedback );
 
  160     const WriterError e = writeDataRaster( pipe, &iter, nCols, nRows, outputExtent, 
crs, transformContext, feedback );
 
  183     QgsDebugMsg( QStringLiteral( 
"Cannot get source data provider" ) );
 
  200   for ( 
int i = 2; i <= nBands; ++i )
 
  212   QList<bool> destHasNoDataValueList;
 
  213   QList<double> destNoDataValueList;
 
  214   QList<Qgis::DataType> destDataTypeList;
 
  215   destDataTypeList.reserve( nBands );
 
  216   destHasNoDataValueList.reserve( nBands );
 
  217   destNoDataValueList.reserve( nBands );
 
  219   const bool isGpkgOutput = mOutputProviderKey == 
"gdal" &&
 
  220                             mOutputFormat.compare( QLatin1String( 
"gpkg" ), Qt::CaseInsensitive ) == 0;
 
  222   double geoTransform[6];
 
  223   globalOutputParameters( outputExtent, nCols, nRows, geoTransform, pixelSize );
 
  224   const auto srcProviderExtent( srcProvider->
extent() );
 
  226   for ( 
int bandNo = 1; bandNo <= nBands; bandNo++ )
 
  231     bool destHasNoDataValue = 
false;
 
  232     double destNoDataValue = std::numeric_limits<double>::quiet_NaN();
 
  237     if ( srcHasNoDataValue )
 
  242       destHasNoDataValue = 
true;
 
  244     else if ( nuller && !nuller->
noData( bandNo ).isEmpty() )
 
  247       destNoDataValue = nuller->
noData( bandNo ).value( 0 ).min();
 
  248       destHasNoDataValue = 
true;
 
  261         ct.setBallparkTransformsAreAppropriate( 
true );
 
  262         outputExtentInSrcCrs = ct.transformBoundingBox( outputExtent );
 
  264       if ( !srcProviderExtent.contains( outputExtentInSrcCrs ) &&
 
  265            ( std::fabs( srcProviderExtent.xMinimum() - outputExtentInSrcCrs.
xMinimum() ) > geoTransform[1] / 2 ||
 
  266              std::fabs( srcProviderExtent.xMaximum() - outputExtentInSrcCrs.
xMaximum() ) > geoTransform[1] / 2 ||
 
  267              std::fabs( srcProviderExtent.yMinimum() - outputExtentInSrcCrs.
yMinimum() ) > std::fabs( geoTransform[5] ) / 2 ||
 
  268              std::fabs( srcProviderExtent.yMaximum() - outputExtentInSrcCrs.
yMaximum() ) > std::fabs( geoTransform[5] ) / 2 ) )
 
  279           destNoDataValue = typeMinValue;
 
  283           destNoDataValue = typeMaxValue;
 
  290         destHasNoDataValue = 
true;
 
  294     if ( nuller && destHasNoDataValue )
 
  299     QgsDebugMsgLevel( QStringLiteral( 
"bandNo = %1 destDataType = %2 destHasNoDataValue = %3 destNoDataValue = %4" ).arg( bandNo ).arg( 
qgsEnumValueToKey( destDataType ) ).arg( destHasNoDataValue ).arg( destNoDataValue ), 4 );
 
  300     destDataTypeList.append( destDataType );
 
  301     destHasNoDataValueList.append( destHasNoDataValue );
 
  302     destNoDataValueList.append( destNoDataValue );
 
  307   for ( 
int i = 1; i < nBands; i++ )
 
  309     if ( destDataTypeList.value( i ) > destDataType )
 
  311       destDataType = destDataTypeList.value( i );
 
  317   for ( 
int attempt = 0; attempt < 2; attempt ++ )
 
  321     std::unique_ptr<QgsRasterDataProvider> destProvider(
 
  322       initOutput( nCols, nRows, 
crs, geoTransform, nBands, destDataType, destHasNoDataValueList, destNoDataValueList ) );
 
  329       if ( !destProvider->isValid() )
 
  331         if ( feedback && !destProvider->error().isEmpty() )
 
  333           feedback->
appendError( destProvider->error().summary() );
 
  337       if ( nCols != destProvider->xSize() || nRows != destProvider->ySize() )
 
  339         QgsDebugMsg( QStringLiteral( 
"Created raster does not have requested dimensions" ) );
 
  342           feedback->
appendError( QObject::tr( 
"Created raster does not have requested dimensions" ) );
 
  346       if ( nBands != destProvider->bandCount() )
 
  348         QgsDebugMsg( QStringLiteral( 
"Created raster does not have requested band count" ) );
 
  351           feedback->
appendError( QObject::tr( 
"Created raster does not have requested band count" ) );
 
  359         destDataType = destProvider->dataType( 1 );
 
  363     error = writeDataRaster( pipe, iter, nCols, nRows, outputExtent, 
crs, destDataType, destHasNoDataValueList, destNoDataValueList, destProvider.get(), feedback );
 
  370         destProvider->remove();
 
  371         destProvider.reset();
 
  379       for ( 
int i = 0; i < nBands; i++ )
 
  381         double destNoDataValue;
 
  383         destDataTypeList.replace( i, destDataType );
 
  384         destNoDataValueList.replace( i, destNoDataValue );
 
  386       destDataType = destDataTypeList.value( 0 );
 
  399 static int qgsDivRoundUp( 
int a, 
int b )
 
  401   return a / b + ( ( ( a % b ) != 0 ) ? 1 : 0 );
 
  406     int nCols, 
int nRows,
 
  410     const QList<bool> &destHasNoDataValueList,
 
  411     const QList<double> &destNoDataValueList,
 
  416   Q_UNUSED( destHasNoDataValueList )
 
  430   std::vector< std::unique_ptr<QgsRasterBlock> > blockList;
 
  431   std::vector< std::unique_ptr<QgsRasterBlock> > destBlockList;
 
  433   blockList.resize( nBands );
 
  434   destBlockList.resize( nBands );
 
  436   for ( 
int i = 1; i <= nBands; ++i )
 
  439     if ( destProvider && destHasNoDataValueList.value( i - 1 ) ) 
 
  441       destProvider->
setNoDataValue( i, destNoDataValueList.value( i - 1 ) );
 
  451     nParts = nPartsX * nPartsY;
 
  458     for ( 
int i = 1; i <= nBands; ++i )
 
  466           const QString vrtFilePath( mOutputUrl + 
'/' + vrtFileName() );
 
  467           writeVRT( vrtFilePath );
 
  470             buildPyramids( vrtFilePath );
 
  477             buildPyramids( mOutputUrl, destProvider );
 
  484       blockList[i - 1].reset( block );
 
  488     if ( feedback && fileIndex < ( nParts - 1 ) )
 
  490       feedback->
setProgress( 100.0 * fileIndex / 
static_cast< double >( nParts ) );
 
  498     for ( 
int i = 1; i <= nBands; ++i )
 
  500       if ( srcProvider && srcProvider->
dataType( i ) == destDataType )
 
  507         blockList[i - 1]->convert( destDataType );
 
  509       destBlockList[i - 1] = std::move( blockList[i - 1] );
 
  514       std::unique_ptr< QgsRasterDataProvider > partDestProvider( createPartProvider( outputExtent,
 
  515           nCols, iterCols, iterRows,
 
  516           iterLeft, iterTop, mOutputUrl,
 
  517           fileIndex, nBands, destDataType, 
crs ) );
 
  519       if ( !partDestProvider || !partDestProvider->isValid() )
 
  525       for ( 
int i = 1; i <= nBands; ++i )
 
  527         if ( destHasNoDataValueList.value( i - 1 ) )
 
  529           partDestProvider->setNoDataValue( i, destNoDataValueList.value( i - 1 ) );
 
  531         if ( destBlockList[ i - 1 ]->isEmpty() )
 
  534         if ( !partDestProvider->write( destBlockList[i - 1]->bits( 0 ), i, iterCols, iterRows, 0, 0 ) )
 
  538         addToVRT( partFileName( fileIndex ), i, iterCols, iterRows, iterLeft, iterTop );
 
  542     else if ( destProvider )
 
  545       for ( 
int i = 1; i <= nBands; ++i )
 
  547         if ( destBlockList[ i - 1 ]->isEmpty() )
 
  550         if ( !destProvider->
write( destBlockList[i - 1]->bits( 0 ), i, iterCols, iterRows, iterLeft, iterTop ) )
 
  586   const size_t nMaxPixels = 
static_cast<size_t>( mMaxTileWidth ) * mMaxTileHeight;
 
  587   std::vector<unsigned char> redData( nMaxPixels );
 
  588   std::vector<unsigned char> greenData( nMaxPixels );
 
  589   std::vector<unsigned char> blueData( nMaxPixels );
 
  590   std::vector<unsigned char> alphaData( nMaxPixels );
 
  591   int iterLeft = 0, iterTop = 0, iterCols = 0, iterRows = 0;
 
  596   double geoTransform[6];
 
  597   globalOutputParameters( outputExtent, nCols, nRows, geoTransform, pixelSize );
 
  599   const int nOutputBands = 4;
 
  600   std::unique_ptr< QgsRasterDataProvider > destProvider( initOutput( nCols, nRows, 
crs, geoTransform, nOutputBands, 
Qgis::DataType::Byte ) );
 
  607     if ( !destProvider->
isValid() )
 
  615     if ( nCols != destProvider->
xSize() || nRows != destProvider->
ySize() )
 
  617       QgsDebugMsg( QStringLiteral( 
"Created raster does not have requested dimensions" ) );
 
  620         feedback->
appendError( QObject::tr( 
"Created raster does not have requested dimensions" ) );
 
  624     if ( nOutputBands != destProvider->
bandCount() )
 
  626       QgsDebugMsg( QStringLiteral( 
"Created raster does not have requested band count" ) );
 
  629         feedback->
appendError( QObject::tr( 
"Created raster does not have requested band count" ) );
 
  635       QgsDebugMsg( QStringLiteral( 
"Created raster does not have requested data type" ) );
 
  638         feedback->
appendError( QObject::tr( 
"Created raster does not have requested data type" ) );
 
  651     nParts = nPartsX * nPartsY;
 
  654   std::unique_ptr< QgsRasterBlock > inputBlock;
 
  655   while ( iter->
readNextRasterPart( 1, iterCols, iterRows, inputBlock, iterLeft, iterTop ) )
 
  657     if ( !inputBlock || inputBlock->isEmpty() )
 
  662     if ( feedback && fileIndex < ( nParts - 1 ) )
 
  664       feedback->
setProgress( 100.0 * fileIndex / 
static_cast< double >( nParts ) );
 
  672     const qgssize nPixels = 
static_cast< qgssize >( iterCols ) * iterRows;
 
  673     for ( 
qgssize i = 0; i < nPixels; ++i )
 
  675       QRgb 
c = inputBlock->color( i );
 
  676       if ( isPremultiplied )
 
  678         c = qUnpremultiply( 
c );
 
  680       redData[i] = 
static_cast<unsigned char>( qRed( 
c ) );
 
  681       greenData[i] = 
static_cast<unsigned char>( qGreen( 
c ) );
 
  682       blueData[i] = 
static_cast<unsigned char>( qBlue( 
c ) );
 
  683       alphaData[i] = 
static_cast<unsigned char>( qAlpha( 
c ) );
 
  689       std::unique_ptr< QgsRasterDataProvider > partDestProvider( createPartProvider( outputExtent,
 
  690           nCols, iterCols, iterRows,
 
  691           iterLeft, iterTop, mOutputUrl, fileIndex,
 
  694       if ( !partDestProvider || partDestProvider->isValid() )
 
  700       if ( !partDestProvider->write( &redData[0], 1, iterCols, iterRows, 0, 0 ) ||
 
  701            !partDestProvider->write( &greenData[0], 2, iterCols, iterRows, 0, 0 ) ||
 
  702            !partDestProvider->write( &blueData[0], 3, iterCols, iterRows, 0, 0 ) ||
 
  703            !partDestProvider->write( &alphaData[0], 4, iterCols, iterRows, 0, 0 ) )
 
  708       addToVRT( partFileName( fileIndex ), 1, iterCols, iterRows, iterLeft, iterTop );
 
  709       addToVRT( partFileName( fileIndex ), 2, iterCols, iterRows, iterLeft, iterTop );
 
  710       addToVRT( partFileName( fileIndex ), 3, iterCols, iterRows, iterLeft, iterTop );
 
  711       addToVRT( partFileName( fileIndex ), 4, iterCols, iterRows, iterLeft, iterTop );
 
  713     else if ( destProvider )
 
  715       if ( !destProvider->
write( &redData[0], 1, iterCols, iterRows, iterLeft, iterTop ) ||
 
  716            !destProvider->
write( &greenData[0], 2, iterCols, iterRows, iterLeft, iterTop ) ||
 
  717            !destProvider->
write( &blueData[0], 3, iterCols, iterRows, iterLeft, iterTop ) ||
 
  718            !destProvider->
write( &alphaData[0], 4, iterCols, iterRows, iterLeft, iterTop ) )
 
  726   destProvider.reset();
 
  735     const QString vrtFilePath( mOutputUrl + 
'/' + vrtFileName() );
 
  736     writeVRT( vrtFilePath );
 
  739       buildPyramids( vrtFilePath );
 
  746       buildPyramids( mOutputUrl );
 
  752 void QgsRasterFileWriter::addToVRT( 
const QString &filename, 
int band, 
int xSize, 
int ySize, 
int xOffset, 
int yOffset )
 
  754   QDomElement bandElem = mVRTBands.value( band - 1 );
 
  756   QDomElement simpleSourceElem = mVRTDocument.createElement( QStringLiteral( 
"SimpleSource" ) );
 
  759   QDomElement sourceFilenameElem = mVRTDocument.createElement( QStringLiteral( 
"SourceFilename" ) );
 
  760   sourceFilenameElem.setAttribute( QStringLiteral( 
"relativeToVRT" ), QStringLiteral( 
"1" ) );
 
  761   const QDomText sourceFilenameText = mVRTDocument.createTextNode( filename );
 
  762   sourceFilenameElem.appendChild( sourceFilenameText );
 
  763   simpleSourceElem.appendChild( sourceFilenameElem );
 
  766   QDomElement sourceBandElem = mVRTDocument.createElement( QStringLiteral( 
"SourceBand" ) );
 
  767   const QDomText sourceBandText = mVRTDocument.createTextNode( QString::number( band ) );
 
  768   sourceBandElem.appendChild( sourceBandText );
 
  769   simpleSourceElem.appendChild( sourceBandElem );
 
  772   QDomElement sourcePropertiesElem = mVRTDocument.createElement( QStringLiteral( 
"SourceProperties" ) );
 
  773   sourcePropertiesElem.setAttribute( QStringLiteral( 
"RasterXSize" ), xSize );
 
  774   sourcePropertiesElem.setAttribute( QStringLiteral( 
"RasterYSize" ), ySize );
 
  775   sourcePropertiesElem.setAttribute( QStringLiteral( 
"BlockXSize" ), xSize );
 
  776   sourcePropertiesElem.setAttribute( QStringLiteral( 
"BlockYSize" ), ySize );
 
  777   sourcePropertiesElem.setAttribute( QStringLiteral( 
"DataType" ), QStringLiteral( 
"Byte" ) );
 
  778   simpleSourceElem.appendChild( sourcePropertiesElem );
 
  781   QDomElement srcRectElem = mVRTDocument.createElement( QStringLiteral( 
"SrcRect" ) );
 
  782   srcRectElem.setAttribute( QStringLiteral( 
"xOff" ), QStringLiteral( 
"0" ) );
 
  783   srcRectElem.setAttribute( QStringLiteral( 
"yOff" ), QStringLiteral( 
"0" ) );
 
  784   srcRectElem.setAttribute( QStringLiteral( 
"xSize" ), xSize );
 
  785   srcRectElem.setAttribute( QStringLiteral( 
"ySize" ), ySize );
 
  786   simpleSourceElem.appendChild( srcRectElem );
 
  789   QDomElement dstRectElem = mVRTDocument.createElement( QStringLiteral( 
"DstRect" ) );
 
  790   dstRectElem.setAttribute( QStringLiteral( 
"xOff" ), xOffset );
 
  791   dstRectElem.setAttribute( QStringLiteral( 
"yOff" ), yOffset );
 
  792   dstRectElem.setAttribute( QStringLiteral( 
"xSize" ), xSize );
 
  793   dstRectElem.setAttribute( QStringLiteral( 
"ySize" ), ySize );
 
  794   simpleSourceElem.appendChild( dstRectElem );
 
  796   bandElem.appendChild( simpleSourceElem );
 
  799 void QgsRasterFileWriter::buildPyramids( 
const QString &filename, 
QgsRasterDataProvider *destProviderIn )
 
  807     destProvider = qobject_cast< QgsRasterDataProvider * >( 
QgsProviderRegistry::instance()->createProvider( mOutputProviderKey, filename, providerOptions ) );
 
  808     if ( !destProvider || !destProvider->
isValid() )
 
  818   QList< QgsRasterPyramid> myPyramidList;
 
  819   if ( ! mPyramidsList.isEmpty() )
 
  821   for ( 
int myCounterInt = 0; myCounterInt < myPyramidList.count(); myCounterInt++ )
 
  823     myPyramidList[myCounterInt].setBuild( 
true );
 
  826   QgsDebugMsgLevel( QStringLiteral( 
"building pyramids : %1 pyramids, %2 resampling, %3 format, %4 options" ).arg( myPyramidList.count() ).arg( mPyramidsResampling ).arg( mPyramidsFormat ).arg( mPyramidsConfigOptions.count() ), 4 );
 
  828   const QString res = destProvider->
buildPyramids( myPyramidList, mPyramidsResampling,
 
  829                       mPyramidsFormat, mPyramidsConfigOptions );
 
  835     QString title, message;
 
  836     if ( res == QLatin1String( 
"ERROR_WRITE_ACCESS" ) )
 
  838       title = QObject::tr( 
"Building Pyramids" );
 
  839       message = QObject::tr( 
"Write access denied. Adjust the file permissions and try again." );
 
  841     else if ( res == QLatin1String( 
"ERROR_WRITE_FORMAT" ) )
 
  843       title = QObject::tr( 
"Building Pyramids" );
 
  844       message = QObject::tr( 
"The file was not writable. Some formats do not " 
  845                              "support pyramid overviews. Consult the GDAL documentation if in doubt." );
 
  847     else if ( res == QLatin1String( 
"FAILED_NOT_SUPPORTED" ) )
 
  849       title = QObject::tr( 
"Building Pyramids" );
 
  850       message = QObject::tr( 
"Building pyramid overviews is not supported on this type of raster." );
 
  852     else if ( res == QLatin1String( 
"ERROR_VIRTUAL" ) )
 
  854       title = QObject::tr( 
"Building Pyramids" );
 
  855       message = QObject::tr( 
"Building pyramid overviews is not supported on this type of raster." );
 
  857     QMessageBox::warning( 
nullptr, title, message );
 
  860   if ( !destProviderIn )
 
  865 int QgsRasterFileWriter::pyramidsProgress( 
double dfComplete, 
const char *pszMessage, 
void *pData )
 
  867   Q_UNUSED( pszMessage )
 
  868   GDALTermProgress( dfComplete, 0, 0 );
 
  869   QProgressDialog *progressDialog = 
static_cast<QProgressDialog *
>( pData );
 
  870   if ( pData && progressDialog->wasCanceled() )
 
  877     progressDialog->setRange( 0, 100 );
 
  878     progressDialog->setValue( dfComplete * 100 );
 
  884 void QgsRasterFileWriter::createVRT( 
int xSize, 
int ySize, 
const QgsCoordinateReferenceSystem &
crs, 
double *geoTransform, 
Qgis::DataType type, 
const QList<bool> &destHasNoDataValueList, 
const QList<double> &destNoDataValueList )
 
  886   mVRTDocument.clear();
 
  887   QDomElement VRTDatasetElem = mVRTDocument.createElement( QStringLiteral( 
"VRTDataset" ) );
 
  890   VRTDatasetElem.setAttribute( QStringLiteral( 
"rasterXSize" ), xSize );
 
  891   VRTDatasetElem.setAttribute( QStringLiteral( 
"rasterYSize" ), ySize );
 
  892   mVRTDocument.appendChild( VRTDatasetElem );
 
  895   QDomElement SRSElem = mVRTDocument.createElement( QStringLiteral( 
"SRS" ) );
 
  896   const QDomText crsText = mVRTDocument.createTextNode( 
crs.
toWkt() );
 
  897   SRSElem.appendChild( crsText );
 
  898   VRTDatasetElem.appendChild( SRSElem );
 
  903     QDomElement geoTransformElem = mVRTDocument.createElement( QStringLiteral( 
"GeoTransform" ) );
 
  904     const QString geoTransformString = QString::number( geoTransform[0], 
'f', 6 ) + 
", " + QString::number( geoTransform[1] ) + 
", " + QString::number( geoTransform[2] ) +
 
  905                                        ", "  + QString::number( geoTransform[3], 
'f', 6 ) + 
", " + QString::number( geoTransform[4] ) + 
", " + QString::number( geoTransform[5] );
 
  906     const QDomText geoTransformText = mVRTDocument.createTextNode( geoTransformString );
 
  907     geoTransformElem.appendChild( geoTransformText );
 
  908     VRTDatasetElem.appendChild( geoTransformElem );
 
  921   QStringList colorInterp;
 
  922   colorInterp << QStringLiteral( 
"Red" ) << QStringLiteral( 
"Green" ) << QStringLiteral( 
"Blue" ) << QStringLiteral( 
"Alpha" );
 
  924   QMap<Qgis::DataType, QString> dataTypes;
 
  936   for ( 
int i = 1; i <= nBands; i++ )
 
  938     QDomElement VRTBand = mVRTDocument.createElement( QStringLiteral( 
"VRTRasterBand" ) );
 
  940     VRTBand.setAttribute( QStringLiteral( 
"band" ), QString::number( i ) );
 
  941     const QString dataType = dataTypes.value( type );
 
  942     VRTBand.setAttribute( QStringLiteral( 
"dataType" ), dataType );
 
  944     if ( mMode == 
Image )
 
  946       VRTBand.setAttribute( QStringLiteral( 
"dataType" ), QStringLiteral( 
"Byte" ) );
 
  947       QDomElement colorInterpElement = mVRTDocument.createElement( QStringLiteral( 
"ColorInterp" ) );
 
  948       const QDomText interpText = mVRTDocument.createTextNode( colorInterp.value( i - 1 ) );
 
  949       colorInterpElement.appendChild( interpText );
 
  950       VRTBand.appendChild( colorInterpElement );
 
  953     if ( !destHasNoDataValueList.isEmpty() && destHasNoDataValueList.value( i - 1 ) )
 
  955       VRTBand.setAttribute( QStringLiteral( 
"NoDataValue" ), QString::number( destNoDataValueList.value( i - 1 ) ) );
 
  958     mVRTBands.append( VRTBand );
 
  959     VRTDatasetElem.appendChild( VRTBand );
 
  963 bool QgsRasterFileWriter::writeVRT( 
const QString &file )
 
  965   QFile outputFile( file );
 
  966   if ( ! outputFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
 
  971   QTextStream outStream( &outputFile );
 
  972   mVRTDocument.save( outStream, 2 );
 
  977     int iterRows, 
int iterLeft, 
int iterTop, 
const QString &outputUrl, 
int fileIndex, 
int nBands, 
Qgis::DataType type,
 
  980   const double mup = extent.
width() / nCols;
 
  981   const double mapLeft = extent.
xMinimum() + iterLeft * mup;
 
  982   const double mapRight = mapLeft + mup * iterCols;
 
  983   const double mapTop = extent.
yMaximum() - iterTop * mup;
 
  984   const double mapBottom = mapTop - iterRows * mup;
 
  985   const QgsRectangle mapRect( mapLeft, mapBottom, mapRight, mapTop );
 
  987   const QString outputFile = 
outputUrl + 
'/' + partFileName( fileIndex );
 
  990   double geoTransform[6];
 
  991   geoTransform[0] = mapRect.xMinimum();
 
  992   geoTransform[1] = mup;
 
  993   geoTransform[2] = 0.0;
 
  994   geoTransform[3] = mapRect.yMaximum();
 
  995   geoTransform[4] = 0.0;
 
  996   geoTransform[5] = -mup;
 
 1003   return destProvider;
 
 1008     const QList<bool> &destHasNoDataValueList, 
const QList<double> &destNoDataValueList )
 
 1012     createVRT( nCols, nRows, 
crs, geoTransform, type, destHasNoDataValueList, destNoDataValueList );
 
 1020     if ( mBuildPyramidsFlag == -4 && mOutputProviderKey == 
"gdal" && mOutputFormat.compare( QLatin1String( 
"gtiff" ), Qt::CaseInsensitive ) == 0 )
 
 1021       mCreateOptions << 
"COPY_SRC_OVERVIEWS=YES";
 
 1026     if ( !destProvider )
 
 1028       QgsDebugMsg( QStringLiteral( 
"No provider created" ) );
 
 1031     return destProvider;
 
 1035 void QgsRasterFileWriter::globalOutputParameters( 
const QgsRectangle &extent, 
int nCols, 
int &nRows,
 
 1036     double *geoTransform, 
double &pixelSize )
 
 1038   pixelSize = extent.
width() / nCols;
 
 1043     nRows = 
static_cast< double >( nCols ) / extent.
width() * extent.
height() + 0.5; 
 
 1045   geoTransform[0] = extent.
xMinimum();
 
 1046   geoTransform[1] = pixelSize;
 
 1047   geoTransform[2] = 0.0;
 
 1048   geoTransform[3] = extent.
yMaximum();
 
 1049   geoTransform[4] = 0.0;
 
 1050   geoTransform[5] = -( extent.
height() / nRows );
 
 1053 QString QgsRasterFileWriter::partFileName( 
int fileIndex )
 
 1056   const QFileInfo outputInfo( mOutputUrl );
 
 1057   return QStringLiteral( 
"%1.%2.tif" ).arg( outputInfo.fileName() ).arg( fileIndex );
 
 1060 QString QgsRasterFileWriter::vrtFileName()
 
 1062   const QFileInfo outputInfo( mOutputUrl );
 
 1063   return QStringLiteral( 
"%1.vrt" ).arg( outputInfo.fileName() );
 
 1068   QString ext = extension.trimmed();
 
 1069   if ( ext.isEmpty() )
 
 1072   if ( ext.startsWith( 
'.' ) )
 
 1076   int const drvCount = GDALGetDriverCount();
 
 1078   for ( 
int i = 0; i < drvCount; ++i )
 
 1080     GDALDriverH drv = GDALGetDriver( i );
 
 1083       char **driverMetadata = GDALGetMetadata( drv, 
nullptr );
 
 1084       if ( CSLFetchBoolean( driverMetadata, GDAL_DCAP_RASTER, 
false ) )
 
 1086         QString drvName = GDALGetDriverShortName( drv );
 
 1087         const QStringList driverExtensions = QString( GDALGetMetadataItem( drv, GDAL_DMD_EXTENSIONS, 
nullptr ) ).split( 
' ' );
 
 1089         const auto constDriverExtensions = driverExtensions;
 
 1090         for ( 
const QString &driver : constDriverExtensions )
 
 1092           if ( driver.compare( ext, Qt::CaseInsensitive ) == 0 )
 
 1103   GDALDriverH drv = GDALGetDriverByName( format.toLocal8Bit().data() );
 
 1106     char **driverMetadata = GDALGetMetadata( drv, 
nullptr );
 
 1107     if ( CSLFetchBoolean( driverMetadata, GDAL_DCAP_RASTER, 
false ) )
 
 1109       return QString( GDALGetMetadataItem( drv, GDAL_DMD_EXTENSIONS, 
nullptr ) ).split( 
' ' );
 
 1112   return QStringList();
 
 1117   GDALDriverH drv = GDALGetDriverByName( driverName.toLocal8Bit().data() );
 
 1120     const QString drvName = GDALGetDriverLongName( drv );
 
 1121     const QString extensionsString = QString( GDALGetMetadataItem( drv, GDAL_DMD_EXTENSIONS, 
nullptr ) );
 
 1122     if ( extensionsString.isEmpty() )
 
 1126     const QStringList extensions = extensionsString.split( 
' ' );
 
 1127     QString filter = drvName + 
" (";
 
 1128     for ( 
const QString &ext : extensions )
 
 1130       filter.append( QStringLiteral( 
"*.%1 *.%2 " ).arg( ext.toLower(), ext.toUpper() ) );
 
 1132     filter = filter.trimmed().append( QStringLiteral( 
")" ) );
 
 1141   static QReadWriteLock sFilterLock;
 
 1142   static QMap< RasterFormatOptions, QList< QgsRasterFileWriter::FilterFormatDetails > > sFilters;
 
 1146   const auto it = sFilters.constFind( options );
 
 1147   if ( it != sFilters.constEnd() )
 
 1151   int const drvCount = GDALGetDriverCount();
 
 1154   QList< QgsRasterFileWriter::FilterFormatDetails > results;
 
 1158   for ( 
int i = 0; i < drvCount; ++i )
 
 1160     GDALDriverH drv = GDALGetDriver( i );
 
 1165         const QString drvName = GDALGetDriverShortName( drv );
 
 1167         if ( filterString.isEmpty() )
 
 1176           if ( drvName == QLatin1String( 
"GTiff" ) )
 
 1178             tifFormat = details;
 
 1190     return a.driverName < b.driverName;
 
 1197       results.insert( 0, tifFormat );
 
 1201   sFilters.insert( options, results );
 
 1209   QStringList extensions;
 
 1211   const QRegularExpression rx( QStringLiteral( 
"\\*\\.([a-zA-Z0-9]*)" ) );
 
 1215     const QString ext = format.filterString;
 
 1216     const QRegularExpressionMatch match = rx.match( ext );
 
 1217     if ( !match.hasMatch() )
 
 1220     const QString matched = match.captured( 1 );
 
 1221     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
Contains a pipeline of raster interfaces for sequential raster processing.
QgsRasterDataProvider * provider() const
Returns the data provider interface, or nullptr if no data provider is present in the pipe.
QgsRasterProjector * projector() const
Returns the projector interface, or nullptr if no projector is present in the pipe.
QgsRasterInterface * last() const
Returns last interface in the pipe.
QgsRasterNuller * nuller() const
Returns the raster nuller interface, or nullptr if no raster nuller is present in the pipe.
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.