24 #include <QCoreApplication>    25 #include <QProgressDialog>    26 #include <QTextStream>    27 #include <QMessageBox>    31     , mOutputUrl( outputUrl )
    32     , mOutputProviderKey( 
"gdal" )
    33     , mOutputFormat( 
"GTiff" )
    35     , mMaxTileWidth( 500 )
    36     , mMaxTileHeight( 500 )
    37     , mBuildPyramidsFlag( 
QgsRaster::PyramidsFlagNo )
    38     , mPyramidsFormat( 
QgsRaster::PyramidsGTiff )
    39     , mProgressDialog( nullptr )
    48     , mOutputProviderKey( 
"gdal" )
    49     , mOutputFormat( 
"GTiff" )
    51     , mMaxTileWidth( 500 )
    52     , mMaxTileHeight( 500 )
    55     , mProgressDialog( 
nullptr )
   102   mProgressDialog = progressDialog;
   121   if ( mMode == 
Image )
   123     WriterError e = writeImageRaster( &iter, nCols, nRows, outputExtent, crs, progressDialog );
   124     mProgressDialog = 
nullptr;
   129     mProgressDialog = 
nullptr;
   130     WriterError e = writeDataRaster( pipe, &iter, nCols, nRows, outputExtent, crs, progressDialog );
   170   for ( 
int i = 2; i <= nBands; ++i )
   185   for ( 
int bandNo = 1; bandNo <= nBands; bandNo++ )
   190     bool destHasNoDataValue = 
false;
   191     double destNoDataValue = std::numeric_limits<double>::quiet_NaN();
   195     if ( srcHasNoDataValue )
   200       destHasNoDataValue = 
true;
   205       destNoDataValue = nuller->
noData( bandNo ).
value( 0 ).min();
   206       destHasNoDataValue = 
true;
   213       if ( projector && projector->
destCrs() != projector->
srcCrs() )
   216         srcExtent = ct.transformBoundingBox( outputExtent );
   229           destNoDataValue = typeMinValue;
   233           destNoDataValue = typeMaxValue;
   240         destHasNoDataValue = 
true;
   244     if ( nuller && destHasNoDataValue )
   249     QgsDebugMsgLevel( 
QString( 
"bandNo = %1 destDataType = %2 destHasNoDataValue = %3 destNoDataValue = %4" ).arg( bandNo ).arg( destDataType ).arg( destHasNoDataValue ).arg( destNoDataValue ), 4 );
   250     destDataTypeList.
append( destDataType );
   251     destHasNoDataValueList.
append( destHasNoDataValue );
   252     destNoDataValueList.
append( destNoDataValue );
   257   for ( 
int i = 1; i < nBands; i++ )
   259     if ( destDataTypeList.
value( i ) > destDataType )
   261       destDataType = destDataTypeList.
value( i );
   269   double geoTransform[6];
   270   globalOutputParameters( outputExtent, nCols, nRows, geoTransform, pixelSize );
   273   destProvider = initOutput( nCols, nRows, crs, geoTransform, nBands, destDataType, destHasNoDataValueList, destNoDataValueList );
   275   WriterError error = writeDataRaster( pipe, iter, nCols, nRows, outputExtent, crs, destDataType, destHasNoDataValueList, destNoDataValueList, destProvider, progressDialog );
   284       destProvider = 
nullptr;
   292     for ( 
int i = 0; i < nBands; i++ )
   294       double destNoDataValue;
   296       destDataTypeList.
replace( i, destDataType );
   297       destNoDataValueList.
replace( i, destNoDataValue );
   299     destDataType =  destDataTypeList.
value( 0 );
   302     destProvider = initOutput( nCols, nRows, crs, geoTransform, nBands, destDataType, destHasNoDataValueList, destNoDataValueList );
   303     error = writeDataRaster( pipe, iter, nCols, nRows, outputExtent, crs, destDataType, destHasNoDataValueList, destNoDataValueList, destProvider, progressDialog );
   315   int nCols, 
int nRows,
   325   Q_UNUSED( destHasNoDataValueList );
   341   for ( 
int i = 1; i <= nBands; ++i )
   345     if ( destProvider && destHasNoDataValueList.
value( i - 1 ) ) 
   353   if ( progressDialog )
   357     nParts = nPartsX * nPartsY;
   359     progressDialog->
show();
   360     progressDialog->
setLabelText( 
QObject::tr( 
"Reading raster part %1 of %2" ).arg( fileIndex + 1 ).arg( nParts ) );
   367     for ( 
int i = 1; i <= nBands; ++i )
   369       if ( !iter->
readNextRasterPart( i, iterCols, iterRows, &( blockList[i - 1] ), iterLeft, iterTop ) )
   374           QString vrtFilePath( mOutputUrl + 
'/' + vrtFileName() );
   375           writeVRT( vrtFilePath );
   378             buildPyramids( vrtFilePath );
   385             buildPyramids( mOutputUrl );
   395     if ( progressDialog && fileIndex < ( nParts - 1 ) )
   397       progressDialog->
setValue( fileIndex + 1 );
   398       progressDialog->
setLabelText( 
QObject::tr( 
"Reading raster part %1 of %2" ).arg( fileIndex + 2 ).arg( nParts ) );
   402         for ( 
int i = 0; i < nBands; ++i )
   412     for ( 
int i = 1; i <= nBands; ++i )
   414       if ( srcProvider && srcProvider->
dataType( i ) == destDataType )
   416         destBlockList.
push_back( blockList[i-1] );
   421         blockList[i-1]->convert( destDataType );
   422         destBlockList.
push_back( blockList[i-1] );
   424       blockList[i-1] = 
nullptr;
   430           nCols, iterCols, iterRows,
   431           iterLeft, iterTop, mOutputUrl,
   432           fileIndex, nBands, destDataType, crs );
   434       if ( partDestProvider )
   437         for ( 
int i = 1; i <= nBands; ++i )
   439           if ( destHasNoDataValueList.
value( i - 1 ) )
   443           partDestProvider->
write( destBlockList[i - 1]->bits( 0 ), i, iterCols, iterRows, 0, 0 );
   444           delete destBlockList[i - 1];
   445           addToVRT( partFileName( fileIndex ), i, iterCols, iterRows, iterLeft, iterTop );
   447         delete partDestProvider;
   450     else if ( destProvider )
   453       for ( 
int i = 1; i <= nBands; ++i )
   455         destProvider->
write( destBlockList[i - 1]->bits( 0 ), i, iterCols, iterRows, iterLeft, iterTop );
   456         delete destBlockList[i - 1];
   488   void* redData = 
qgsMalloc( mMaxTileWidth * mMaxTileHeight );
   489   void* greenData = 
qgsMalloc( mMaxTileWidth * mMaxTileHeight );
   490   void* blueData = 
qgsMalloc( mMaxTileWidth * mMaxTileHeight );
   491   void* alphaData = 
qgsMalloc( mMaxTileWidth * mMaxTileHeight );
   493   int iterLeft = 0, iterTop = 0, iterCols = 0, iterRows = 0;
   499   double geoTransform[6];
   500   globalOutputParameters( outputExtent, nCols, nRows, geoTransform, pixelSize );
   502   destProvider = initOutput( nCols, nRows, crs, geoTransform, 4, 
QGis::Byte );
   507   if ( progressDialog )
   511     nParts = nPartsX * nPartsY;
   513     progressDialog->
show();
   514     progressDialog->
setLabelText( 
QObject::tr( 
"Reading raster part %1 of %2" ).arg( fileIndex + 1 ).arg( nParts ) );
   518   while ( iter->
readNextRasterPart( 1, iterCols, iterRows, &inputBlock, iterLeft, iterTop ) )
   525     if ( progressDialog && fileIndex < ( nParts - 1 ) )
   527       progressDialog->
setValue( fileIndex + 1 );
   528       progressDialog->
setLabelText( 
QObject::tr( 
"Reading raster part %1 of %2" ).arg( fileIndex + 2 ).arg( nParts ) );
   544     for ( 
qgssize i = 0; i < nPixels; ++i )
   546       QRgb c = inputBlock->
color( i );
   554         double a = alpha / 255.;
   555         QgsDebugMsgLevel( 
QString( 
"red = %1 green = %2 blue = %3 alpha = %4 p = %5 a = %6" ).arg( red ).arg( green ).arg( blue ).arg( alpha ).arg( static_cast< int >( c ), 0, 16 ).arg( a ), 5 );
   560       memcpy( reinterpret_cast< char* >( redData ) + i, &red, 1 );
   561       memcpy( reinterpret_cast< char* >( greenData ) + i, &green, 1 );
   562       memcpy( reinterpret_cast< char* >( blueData ) + i, &blue, 1 );
   563       memcpy( reinterpret_cast< char* >( alphaData ) + i, &alpha, 1 );
   572           nCols, iterCols, iterRows,
   573           iterLeft, iterTop, mOutputUrl, fileIndex,
   576       if ( partDestProvider )
   579         partDestProvider->
write( redData, 1, iterCols, iterRows, 0, 0 );
   580         partDestProvider->
write( greenData, 2, iterCols, iterRows, 0, 0 );
   581         partDestProvider->
write( blueData, 3, iterCols, iterRows, 0, 0 );
   582         partDestProvider->
write( alphaData, 4, iterCols, iterRows, 0, 0 );
   584         addToVRT( partFileName( fileIndex ), 1, iterCols, iterRows, iterLeft, iterTop );
   585         addToVRT( partFileName( fileIndex ), 2, iterCols, iterRows, iterLeft, iterTop );
   586         addToVRT( partFileName( fileIndex ), 3, iterCols, iterRows, iterLeft, iterTop );
   587         addToVRT( partFileName( fileIndex ), 4, iterCols, iterRows, iterLeft, iterTop );
   588         delete partDestProvider;
   591     else if ( destProvider )
   593       destProvider->
write( redData, 1, iterCols, iterRows, iterLeft, iterTop );
   594       destProvider->
write( greenData, 2, iterCols, iterRows, iterLeft, iterTop );
   595       destProvider->
write( blueData, 3, iterCols, iterRows, iterLeft, iterTop );
   596       destProvider->
write( alphaData, 4, iterCols, iterRows, iterLeft, iterTop );
   610   if ( progressDialog )
   617     QString vrtFilePath( mOutputUrl + 
'/' + vrtFileName() );
   618     writeVRT( vrtFilePath );
   621       buildPyramids( vrtFilePath );
   628       buildPyramids( mOutputUrl );
   634 void QgsRasterFileWriter::addToVRT( 
const QString& filename, 
int band, 
int xSize, 
int ySize, 
int xOffset, 
int yOffset )
   642   sourceFilenameElem.
setAttribute( 
"relativeToVRT", 
"1" );
   644   sourceFilenameElem.
appendChild( sourceFilenameText );
   645   simpleSourceElem.
appendChild( sourceFilenameElem );
   655   sourcePropertiesElem.
setAttribute( 
"RasterXSize", xSize );
   656   sourcePropertiesElem.
setAttribute( 
"RasterYSize", ySize );
   657   sourcePropertiesElem.
setAttribute( 
"BlockXSize", xSize );
   658   sourcePropertiesElem.
setAttribute( 
"BlockYSize", ySize );
   659   sourcePropertiesElem.
setAttribute( 
"DataType", 
"Byte" );
   660   simpleSourceElem.
appendChild( sourcePropertiesElem );
   682 void QgsRasterFileWriter::buildPyramids( 
const QString& filename )
   697   overviewList[3] = 16;
   698   overviewList[4] = 32;
   699   overviewList[5] = 64;
   702   if ( mProgressDialog )
   707     mProgressDialog->
show();
   710   GDALBuildOverviews( dataSet, 
"AVERAGE", 6, overviewList, 0, 0,  0,  0 );
   714 void QgsRasterFileWriter::buildPyramids( 
const QString& filename )
   728   if ( ! mPyramidsList.
isEmpty() )
   730   for ( 
int myCounterInt = 0; myCounterInt < myPyramidList.
count(); myCounterInt++ )
   732     myPyramidList[myCounterInt].build = 
true;
   735   QgsDebugMsgLevel( 
QString( 
"building pyramids : %1 pyramids, %2 resampling, %3 format, %4 options" ).arg( myPyramidList.
count() ).arg( mPyramidsResampling ).
arg( mPyramidsFormat ).
arg( mPyramidsConfigOptions.
count() ), 4 );
   738                 mPyramidsFormat, mPyramidsConfigOptions );
   745     if ( res == 
"ERROR_WRITE_ACCESS" )
   747       title = 
QObject::tr( 
"Building pyramids failed - write access denied" );
   748       message = 
QObject::tr( 
"Write access denied. Adjust the file permissions and try again." );
   750     else if ( res == 
"ERROR_WRITE_FORMAT" )
   752       title = 
QObject::tr( 
"Building pyramids failed." );
   753       message = 
QObject::tr( 
"The file was not writable. Some formats do not "   754                              "support pyramid overviews. Consult the GDAL documentation if in doubt." );
   756     else if ( res == 
"FAILED_NOT_SUPPORTED" )
   758       title = 
QObject::tr( 
"Building pyramids failed." );
   759       message = 
QObject::tr( 
"Building pyramid overviews is not supported on this type of raster." );
   761     else if ( res == 
"ERROR_JPEG_COMPRESSION" )
   763       title = 
QObject::tr( 
"Building pyramids failed." );
   764       message = 
QObject::tr( 
"Building internal pyramid overviews is not supported on raster layers with JPEG compression and your current libtiff library." );
   766     else if ( res == 
"ERROR_VIRTUAL" )
   768       title = 
QObject::tr( 
"Building pyramids failed." );
   769       message = 
QObject::tr( 
"Building pyramid overviews is not supported on this type of raster." );
   778 int QgsRasterFileWriter::pyramidsProgress( 
double dfComplete, 
const char *pszMessage, 
void* pData )
   780   Q_UNUSED( pszMessage );
   781   GDALTermProgress( dfComplete, 0, 0 );
   791     progressDialog->
setValue( dfComplete * 100 );
   799   mVRTDocument.
clear();
   835   colorInterp << 
"Red" << 
"Green" << 
"Blue" << 
"Alpha";
   849   for ( 
int i = 1; i <= nBands; i++ )
   857     if ( mMode == 
Image )
   866     if ( !destHasNoDataValueList.
isEmpty() && destHasNoDataValueList.
value( i - 1 ) )
   871     mVRTBands.
append( VRTBand );
   876 bool QgsRasterFileWriter::writeVRT( 
const QString& file )
   878   QFile outputFile( file );
   879   if ( ! outputFile.
open( QIODevice::WriteOnly | QIODevice::Truncate ) )
   885   mVRTDocument.
save( outStream, 2 );
   890     int iterRows, 
int iterLeft, 
int iterTop, 
const QString& outputUrl, 
int fileIndex, 
int nBands, 
QGis::DataType type,
   893   double mup = extent.
width() / nCols;
   894   double mapLeft = extent.
xMinimum() + iterLeft * mup;
   895   double mapRight = mapLeft + mup * iterCols;
   896   double mapTop = extent.
yMaximum() - iterTop * mup;
   897   double mapBottom = mapTop - iterRows * mup;
   898   QgsRectangle mapRect( mapLeft, mapBottom, mapRight, mapTop );
   900   QString outputFile = outputUrl + 
'/' + partFileName( fileIndex );
   903   double geoTransform[6];
   904   geoTransform[0] = mapRect.
xMinimum();
   905   geoTransform[1] = mup;
   906   geoTransform[2] = 0.0;
   907   geoTransform[3] = mapRect.
yMaximum();
   908   geoTransform[4] = 0.0;
   909   geoTransform[5] = -mup;
   925     createVRT( nCols, nRows, crs, geoTransform, type, destHasNoDataValueList, destNoDataValueList );
   933     if ( mBuildPyramidsFlag == -4 && mOutputProviderKey == 
"gdal" && mOutputFormat.
toLower() == 
"gtiff" )
   934       mCreateOptions << 
"COPY_SRC_OVERVIEWS=YES";
   948 void QgsRasterFileWriter::globalOutputParameters( 
const QgsRectangle& extent, 
int nCols, 
int& nRows,
   949     double* geoTransform, 
double& pixelSize )
   951   pixelSize = extent.
width() / nCols;
   956     nRows = 
static_cast< double >( nCols ) / extent.
width() * extent.
height() + 0.5;
   958   geoTransform[0] = extent.
xMinimum();
   959   geoTransform[1] = pixelSize;
   960   geoTransform[2] = 0.0;
   961   geoTransform[3] = extent.
yMaximum();
   962   geoTransform[4] = 0.0;
   963   geoTransform[5] = -( extent.
height() / nRows );
   966 QString QgsRasterFileWriter::partFileName( 
int fileIndex )
   973 QString QgsRasterFileWriter::vrtFileName()
 virtual int bandCount() const =0
Get number of bands. 
 
Eight bit unsigned integer (quint8) 
 
bool contains(const QgsRectangle &rect) const
return true when rectangle contains other rectangle 
 
static QgsProviderRegistry * instance(const QString &pluginPath=QString::null)
Means of accessing canonical single instance. 
 
A rectangle specified with double values. 
 
QgsRasterFileWriter(const QString &outputUrl)
 
Base class for processing modules. 
 
void * qgsMalloc(size_t size)
Allocates size bytes and returns a pointer to the allocated memory. 
 
Iterator for sequentially processing raster cells. 
 
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. 
 
QDomNode appendChild(const QDomNode &newChild)
 
void setMaximum(int maximum)
 
void push_back(const T &value)
 
void setLabelText(const QString &text)
 
QgsRasterProjector * projector() const
 
Raster pipe that deals with null values. 
 
QgsRasterInterface * last() const
 
double maximumValue
The maximum cell value in the raster band. 
 
Thirty two bit floating point (float) 
 
static double maximumValuePossible(QGis::DataType)
Helper function that returns the maximum possible value for a GDAL data type. 
 
virtual bool setNoDataValue(int bandNo, double noDataValue)
Set no data value on created dataset. 
 
QgsCoordinateReferenceSystem srcCrs() const
Get source CRS. 
 
QString tr(const char *sourceText, const char *disambiguation, int n)
 
QgsCoordinateReferenceSystem destCrs() const
Get destination CRS. 
 
virtual QgsRasterBandStats bandStatistics(int theBandNo, int theStats=QgsRasterBandStats::All, const QgsRectangle &theExtent=QgsRectangle(), int theSampleSize=0)
Get band statistics. 
 
void setValue(int progress)
 
static QGis::DataType typeWithNoDataValue(QGis::DataType dataType, double *noDataValue)
For given data type returns wider type and sets no data value. 
 
QString number(int n, int base)
 
int count(const T &value) const
 
The RasterBandStats struct is a container for statistics about a single raster band. 
 
void processEvents(QFlags< QEventLoop::ProcessEventsFlag > flags)
 
void append(const T &value)
 
Sixteen bit unsigned integer (quint16) 
 
Sixty four bit floating point (double) 
 
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32_Premultiplied. 
 
QgsDataProvider * provider(const QString &providerKey, const QString &dataSource)
Create an instance of the provider. 
 
#define QgsDebugMsgLevel(str, level)
 
virtual QGis::DataType srcDataType(int bandNo) const override=0
Returns source data type for the band specified by number, source data type may be shorter than dataT...
 
virtual QList< QgsRasterPyramid > buildPyramidList(QList< int > overviewList=QList< int >())
Accessor for ths raster layers pyramid list. 
 
void setAttribute(const QString &name, const QString &value)
 
double width() const
Width of the rectangle. 
 
static bool typeIsColor(QGis::DataType type)
Returns true if data type is color. 
 
Thirty two bit unsigned integer (quint32) 
 
QRgb color(int row, int column) const
Read a single color. 
 
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32. 
 
static int typeSize(int dataType)
 
QgsRasterRangeList noData(int bandNo) const
 
virtual QGis::DataType dataType(int bandNo) const =0
Returns data type for the band specified by number. 
 
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...
 
void setRange(int minimum, int maximum)
 
virtual bool open(QFlags< QIODevice::OpenModeFlag > mode)
 
Base class for processing filters like renderers, reprojector, resampler etc. 
 
Sixteen bit signed integer (qint16) 
 
QDomText createTextNode(const QString &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...
 
QByteArray toLocal8Bit() const
 
void setOutputNoDataValue(int bandNo, double noData)
Set output no data value. 
 
QgsRasterProjector implements approximate projection support for it calculates grid of points in sour...
 
virtual QgsRectangle extent() override=0
Get the extent of the data source. 
 
void setMaximumTileWidth(int w)
 
virtual QGis::DataType dataType(int bandNo) const override=0
Returns data type for the band specified by number. 
 
void setMaximumTileHeight(int h)
 
void save(QTextStream &str, int indent) const
 
const QgsRasterInterface * input() const
 
int maximumTileHeight() const
 
QString absolutePath() const
 
virtual bool remove()
Remove dataset. 
 
bool mkdir(const QString &dirName) const
 
Class for storing a coordinate reference system (CRS) 
 
QString toWkt() const
Returns a WKT representation of this CRS. 
 
DataType
Raster data types. 
 
double xMinimum() const
Get the x minimum value (left side of rectangle) 
 
virtual const QgsRasterInterface * srcInput() const
Get source / raw input, the first in pipe, usually provider. 
 
double minimumValue
The minimum cell value in the raster band. 
 
QgsRasterNuller * nuller() const
 
virtual QString buildPyramids(const QList< QgsRasterPyramid > &thePyramidList, const QString &theResamplingMethod="NEAREST", QgsRaster::RasterPyramidsFormat theFormat=QgsRaster::PyramidsGTiff, const QStringList &theConfigOptions=QStringList())
Create pyramid overviews. 
 
StandardButton warning(QWidget *parent, const QString &title, const QString &text, QFlags< QMessageBox::StandardButton > buttons, StandardButton defaultButton)
 
double yMaximum() const
Get the y maximum value (top side of rectangle) 
 
iterator insert(const Key &key, const T &value)
 
virtual bool write(void *data, int band, int width, int height, int xOffset, int yOffset)
Writes into the provider datasource. 
 
virtual bool srcHasNoDataValue(int bandNo) const
Return true if source band has no data value. 
 
QDomElement createElement(const QString &tagName)
 
virtual double srcNoDataValue(int bandNo) const
Value representing no data value. 
 
WriterError writeRaster(const QgsRasterPipe *pipe, int nCols, int nRows, QgsRectangle outputExtent, const QgsCoordinateReferenceSystem &crs, QProgressDialog *p=nullptr)
Write raster file. 
 
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
 
void qgsFree(void *ptr)
Frees the memory space pointed to by ptr. 
 
void startRasterRead(int bandNumber, int nCols, int nRows, const QgsRectangle &extent, QgsRasterBlockFeedback *feedback=nullptr)
Start reading of raster band. 
 
int maximumTileWidth() const
 
double height() const
Height of the rectangle. 
 
const T value(const Key &key) const
 
Base class for raster data providers. 
 
void replace(int i, const T &value)