24 #include <QCoreApplication>
25 #include <QProgressDialog>
26 #include <QTextStream>
27 #include <QMessageBox>
30 mMode( Raw ), mOutputUrl( outputUrl ), mOutputProviderKey(
"gdal" ), mOutputFormat(
"GTiff" ),
31 mTiledMode( false ), mMaxTileWidth( 500 ), mMaxTileHeight( 500 ),
32 mBuildPyramidsFlag(
QgsRaster::PyramidsFlagNo ),
33 mPyramidsFormat(
QgsRaster::PyramidsGTiff ),
34 mProgressDialog( 0 ), mPipe( 0 ), mInput( 0 )
77 QgsDebugMsg( QString(
"reading from %1" ).arg(
typeid( *iface ).name() ) );
94 if ( !fileInfo.exists() )
96 QDir dir = fileInfo.dir();
97 if ( !dir.mkdir( fileInfo.fileName() ) )
99 QgsDebugMsg(
"Cannot create output VRT directory " + fileInfo.fileName() +
" in " + dir.absolutePath() );
154 for (
int i = 2; i <= nBands; ++i )
166 QList<bool> destHasNoDataValueList;
167 QList<double> destNoDataValueList;
168 QList<QGis::DataType> destDataTypeList;
169 for (
int bandNo = 1; bandNo <= nBands; bandNo++ )
174 bool destHasNoDataValue =
false;
175 double destNoDataValue = std::numeric_limits<double>::quiet_NaN();
178 QgsDebugMsg( QString(
"srcHasNoDataValue = %1 srcNoDataValue = %2" ).arg( srcHasNoDataValue ).arg( srcProvider->
srcNoDataValue( bandNo ) ) );
179 if ( srcHasNoDataValue )
184 destHasNoDataValue =
true;
186 else if ( nuller && nuller->
noData( bandNo ).size() > 0 )
189 destNoDataValue = nuller->
noData( bandNo ).value( 0 ).min();
190 destHasNoDataValue =
true;
197 if ( projector && projector->
destCrs() != projector->
srcCrs() )
200 srcExtent = ct.transformBoundingBox( outputExtent );
213 destNoDataValue = typeMinValue;
217 destNoDataValue = typeMaxValue;
224 destHasNoDataValue =
true;
228 if ( nuller && destHasNoDataValue )
233 QgsDebugMsg( QString(
"bandNo = %1 destDataType = %2 destHasNoDataValue = %3 destNoDataValue = %4" ).arg( bandNo ).arg( destDataType ).arg( destHasNoDataValue ).arg( destNoDataValue ) );
234 destDataTypeList.append( destDataType );
235 destHasNoDataValueList.append( destHasNoDataValue );
236 destNoDataValueList.append( destNoDataValue );
241 for (
int i = 1; i < nBands; i++ )
243 if ( destDataTypeList.value( i ) > destDataType )
245 destDataType = destDataTypeList.value( i );
253 double geoTransform[6];
257 destProvider =
initOutput( nCols, nRows, crs, geoTransform, nBands, destDataType, destHasNoDataValueList, destNoDataValueList );
259 WriterError error =
writeDataRaster( pipe, iter, nCols, nRows, outputExtent, crs, destDataType, destHasNoDataValueList, destNoDataValueList, destProvider, progressDialog );
276 for (
int i = 0; i < nBands; i++ )
278 double destNoDataValue;
280 destDataTypeList.replace( i, destDataType );
281 destNoDataValueList.replace( i, destNoDataValue );
283 destDataType = destDataTypeList.value( 0 );
286 destProvider =
initOutput( nCols, nRows, crs, geoTransform, nBands, destDataType , destHasNoDataValueList, destNoDataValueList );
287 error =
writeDataRaster( pipe, iter, nCols, nRows, outputExtent, crs, destDataType, destHasNoDataValueList, destNoDataValueList, destProvider, progressDialog );
299 int nCols,
int nRows,
303 QList<bool> destHasNoDataValueList,
304 QList<double> destNoDataValueList,
306 QProgressDialog* progressDialog )
309 Q_UNUSED( destHasNoDataValueList );
315 QgsDebugMsg( QString(
"nBands = %1" ).arg( nBands ) );
323 QList<QgsRasterBlock*> blockList;
324 for (
int i = 1; i <= nBands; ++i )
327 blockList.push_back( 0 );
330 destProvider->
setNoDataValue( i, destNoDataValueList.value( i - 1 ) );
336 if ( progressDialog )
340 nParts = nPartsX * nPartsY;
341 progressDialog->setMaximum( nParts );
342 progressDialog->show();
343 progressDialog->setLabelText(
QObject::tr(
"Reading raster part %1 of %2" ).arg( fileIndex + 1 ).arg( nParts ) );
350 for (
int i = 1; i <= nBands; ++i )
352 if ( !iter->
readNextRasterPart( i, iterCols, iterRows, &( blockList[i - 1] ), iterLeft, iterTop ) )
378 if ( progressDialog && fileIndex < ( nParts - 1 ) )
380 progressDialog->setValue( fileIndex + 1 );
381 progressDialog->setLabelText(
QObject::tr(
"Reading raster part %1 of %2" ).arg( fileIndex + 2 ).arg( nParts ) );
382 QCoreApplication::processEvents( QEventLoop::AllEvents, 1000 );
383 if ( progressDialog->wasCanceled() )
385 for (
int i = 0; i < nBands; ++i )
394 QList<QgsRasterBlock*> destBlockList;
395 for (
int i = 1; i <= nBands; ++i )
397 if ( srcProvider->
dataType( i ) == destDataType )
399 destBlockList.push_back( blockList[i-1] );
404 blockList[i-1]->convert( destDataType );
405 destBlockList.push_back( blockList[i-1] );
413 nCols, iterCols, iterRows,
415 fileIndex, nBands, destDataType, crs );
417 if ( partDestProvider )
420 for (
int i = 1; i <= nBands; ++i )
422 partDestProvider->
setNoDataValue( i, destNoDataValueList.value( i - 1 ) );
423 partDestProvider->
write( destBlockList[i - 1]->bits( 0 ), i, iterCols, iterRows, 0, 0 );
424 delete destBlockList[i - 1];
427 delete partDestProvider;
430 else if ( destProvider )
433 for (
int i = 1; i <= nBands; ++i )
435 destProvider->
write( destBlockList[i - 1]->bits( 0 ), i, iterCols, iterRows, iterLeft, iterTop );
436 delete destBlockList[i - 1];
471 int iterLeft = 0, iterTop = 0, iterCols = 0, iterRows = 0;
477 double geoTransform[6];
485 if ( progressDialog )
489 nParts = nPartsX * nPartsY;
490 progressDialog->setMaximum( nParts );
491 progressDialog->show();
492 progressDialog->setLabelText(
QObject::tr(
"Reading raster part %1 of %2" ).arg( fileIndex + 1 ).arg( nParts ) );
496 while ( iter->
readNextRasterPart( 1, iterCols, iterRows, &inputBlock, iterLeft, iterTop ) )
503 if ( progressDialog && fileIndex < ( nParts - 1 ) )
505 progressDialog->
setValue( fileIndex + 1 );
506 progressDialog->setLabelText(
QObject::tr(
"Reading raster part %1 of %2" ).arg( fileIndex + 2 ).arg( nParts ) );
507 QCoreApplication::processEvents( QEventLoop::AllEvents, 1000 );
508 if ( progressDialog->wasCanceled() )
522 for (
qgssize i = 0; i < nPixels; ++i )
524 QRgb c = inputBlock->
color( i );
526 red = qRed( c ); green = qGreen( c ); blue = qBlue( c );
530 double a = alpha / 255.;
531 QgsDebugMsgLevel( QString(
"red = %1 green = %2 blue = %3 alpha = %4 p = %5 a = %6" ).arg( red ).arg( green ).arg( blue ).arg( alpha ).arg((
int )c, 0, 16 ).arg( a ), 5 );
536 memcpy((
char* )redData + i, &red, 1 );
537 memcpy((
char* )greenData + i, &green, 1 );
538 memcpy((
char* )blueData + i, &blue, 1 );
539 memcpy((
char* )alphaData + i, &alpha, 1 );
548 nCols, iterCols, iterRows,
552 if ( partDestProvider )
555 partDestProvider->
write( redData, 1, iterCols, iterRows, 0, 0 );
556 partDestProvider->
write( greenData, 2, iterCols, iterRows, 0, 0 );
557 partDestProvider->
write( blueData, 3, iterCols, iterRows, 0, 0 );
558 partDestProvider->
write( alphaData, 4, iterCols, iterRows, 0, 0 );
564 delete partDestProvider;
567 else if ( destProvider )
569 destProvider->
write( redData, 1, iterCols, iterRows, iterLeft, iterTop );
570 destProvider->
write( greenData, 2, iterCols, iterRows, iterLeft, iterTop );
571 destProvider->
write( blueData, 3, iterCols, iterRows, iterLeft, iterTop );
572 destProvider->
write( alphaData, 4, iterCols, iterRows, iterLeft, iterTop );
583 if ( progressDialog )
585 progressDialog->setValue( progressDialog->maximum() );
609 QDomElement bandElem =
mVRTBands.value( band - 1 );
611 QDomElement simpleSourceElem =
mVRTDocument.createElement(
"SimpleSource" );
614 QDomElement sourceFilenameElem =
mVRTDocument.createElement(
"SourceFilename" );
615 sourceFilenameElem.setAttribute(
"relativeToVRT",
"1" );
616 QDomText sourceFilenameText =
mVRTDocument.createTextNode( filename );
617 sourceFilenameElem.appendChild( sourceFilenameText );
618 simpleSourceElem.appendChild( sourceFilenameElem );
621 QDomElement sourceBandElem =
mVRTDocument.createElement(
"SourceBand" );
622 QDomText sourceBandText =
mVRTDocument.createTextNode( QString::number( band ) );
623 sourceBandElem.appendChild( sourceBandText );
624 simpleSourceElem.appendChild( sourceBandElem );
627 QDomElement sourcePropertiesElem =
mVRTDocument.createElement(
"SourceProperties" );
628 sourcePropertiesElem.setAttribute(
"RasterXSize", xSize );
629 sourcePropertiesElem.setAttribute(
"RasterYSize", ySize );
630 sourcePropertiesElem.setAttribute(
"BlockXSize", xSize );
631 sourcePropertiesElem.setAttribute(
"BlockYSize", ySize );
632 sourcePropertiesElem.setAttribute(
"DataType",
"Byte" );
633 simpleSourceElem.appendChild( sourcePropertiesElem );
636 QDomElement srcRectElem =
mVRTDocument.createElement(
"SrcRect" );
637 srcRectElem.setAttribute(
"xOff",
"0" );
638 srcRectElem.setAttribute(
"yOff",
"0" );
639 srcRectElem.setAttribute(
"xSize", xSize );
640 srcRectElem.setAttribute(
"ySize", ySize );
641 simpleSourceElem.appendChild( srcRectElem );
644 QDomElement dstRectElem =
mVRTDocument.createElement(
"DstRect" );
645 dstRectElem.setAttribute(
"xOff", xOffset );
646 dstRectElem.setAttribute(
"yOff", yOffset );
647 dstRectElem.setAttribute(
"xSize", xSize );
648 dstRectElem.setAttribute(
"ySize", ySize );
649 simpleSourceElem.appendChild( dstRectElem );
651 bandElem.appendChild( simpleSourceElem );
657 GDALDatasetH dataSet;
659 dataSet = GDALOpen( filename.toLocal8Bit().data(), GA_Update );
670 overviewList[3] = 16;
671 overviewList[4] = 32;
672 overviewList[5] = 64;
683 GDALBuildOverviews( dataSet,
"AVERAGE", 6, overviewList, 0, 0, 0, 0 );
700 QList< QgsRasterPyramid> myPyramidList;
703 for (
int myCounterInt = 0; myCounterInt < myPyramidList.count(); myCounterInt++ )
705 myPyramidList[myCounterInt].build =
true;
717 QString title, message;
718 if ( res ==
"ERROR_WRITE_ACCESS" )
720 title =
QObject::tr(
"Building pyramids failed - write access denied" );
721 message =
QObject::tr(
"Write access denied. Adjust the file permissions and try again." );
723 else if ( res ==
"ERROR_WRITE_FORMAT" )
725 title =
QObject::tr(
"Building pyramids failed." );
726 message =
QObject::tr(
"The file was not writable. Some formats do not "
727 "support pyramid overviews. Consult the GDAL documentation if in doubt." );
729 else if ( res ==
"FAILED_NOT_SUPPORTED" )
731 title =
QObject::tr(
"Building pyramids failed." );
732 message =
QObject::tr(
"Building pyramid overviews is not supported on this type of raster." );
734 else if ( res ==
"ERROR_JPEG_COMPRESSION" )
736 title =
QObject::tr(
"Building pyramids failed." );
737 message =
QObject::tr(
"Building internal pyramid overviews is not supported on raster layers with JPEG compression and your current libtiff library." );
739 else if ( res ==
"ERROR_VIRTUAL" )
741 title =
QObject::tr(
"Building pyramids failed." );
742 message =
QObject::tr(
"Building pyramid overviews is not supported on this type of raster." );
744 QMessageBox::warning( 0, title, message );
751 int QgsRasterFileWriter::pyramidsProgress(
double dfComplete,
const char *pszMessage,
void* pData )
753 Q_UNUSED( pszMessage );
754 GDALTermProgress( dfComplete, 0, 0 );
755 QProgressDialog* progressDialog =
static_cast<QProgressDialog*
>( pData );
756 if ( pData && progressDialog->wasCanceled() )
763 progressDialog->setRange( 0, 100 );
764 progressDialog->setValue( dfComplete * 100 );
773 QDomElement VRTDatasetElem =
mVRTDocument.createElement(
"VRTDataset" );
776 VRTDatasetElem.setAttribute(
"rasterXSize", xSize );
777 VRTDatasetElem.setAttribute(
"rasterYSize", ySize );
781 QDomElement SRSElem =
mVRTDocument.createElement(
"SRS" );
783 SRSElem.appendChild( crsText );
784 VRTDatasetElem.appendChild( SRSElem );
789 QDomElement geoTransformElem =
mVRTDocument.createElement(
"GeoTransform" );
790 QString geoTransformString = QString::number( geoTransform[0] ) +
", " + QString::number( geoTransform[1] ) +
", " + QString::number( geoTransform[2] ) +
791 ", " + QString::number( geoTransform[3] ) +
", " + QString::number( geoTransform[4] ) +
", " + QString::number( geoTransform[5] );
792 QDomText geoTransformText =
mVRTDocument.createTextNode( geoTransformString );
793 geoTransformElem.appendChild( geoTransformText );
794 VRTDatasetElem.appendChild( geoTransformElem );
807 QStringList colorInterp;
808 colorInterp <<
"Red" <<
"Green" <<
"Blue" <<
"Alpha";
810 QMap<QGis::DataType, QString> dataTypes;
822 for (
int i = 1; i <= nBands; i++ )
824 QDomElement VRTBand =
mVRTDocument.createElement(
"VRTRasterBand" );
826 VRTBand.setAttribute(
"band", QString::number( i ) );
827 QString dataType = dataTypes.value( type );
828 VRTBand.setAttribute(
"dataType", dataType );
832 VRTBand.setAttribute(
"dataType",
"Byte" );
833 QDomElement colorInterpElement =
mVRTDocument.createElement(
"ColorInterp" );
834 QDomText interpText =
mVRTDocument.createTextNode( colorInterp.value( i - 1 ) );
835 colorInterpElement.appendChild( interpText );
836 VRTBand.appendChild( colorInterpElement );
839 if ( !destHasNoDataValueList.isEmpty() && destHasNoDataValueList.value( i - 1 ) )
841 VRTBand.setAttribute(
"NoDataValue", QString::number( destNoDataValueList.value( i - 1 ) ) );
845 VRTDatasetElem.appendChild( VRTBand );
851 QFile outputFile( file );
852 if ( ! outputFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
857 QTextStream outStream( &outputFile );
863 int iterRows,
int iterLeft,
int iterTop,
const QString& outputUrl,
int fileIndex,
int nBands,
QGis::DataType type,
866 double mup = extent.
width() / nCols;
867 double mapLeft = extent.
xMinimum() + iterLeft * mup;
868 double mapRight = mapLeft + mup * iterCols;
869 double mapTop = extent.
yMaximum() - iterTop * mup;
870 double mapBottom = mapTop - iterRows * mup;
871 QgsRectangle mapRect( mapLeft, mapBottom, mapRight, mapTop );
873 QString outputFile = outputUrl +
"/" +
partFileName( fileIndex );
876 double geoTransform[6];
877 geoTransform[0] = mapRect.
xMinimum();
878 geoTransform[1] = mup;
879 geoTransform[2] = 0.0;
880 geoTransform[3] = mapRect.
yMaximum();
881 geoTransform[4] = 0.0;
882 geoTransform[5] = -mup;
894 QList<bool> destHasNoDataValueList, QList<double> destNoDataValueList )
898 createVRT( nCols, nRows, crs, geoTransform, type, destHasNoDataValueList, destNoDataValueList );
922 double* geoTransform,
double& pixelSize )
924 pixelSize = extent.
width() / nCols;
929 nRows = ( double )nCols / extent.
width() * extent.
height() + 0.5;
931 geoTransform[0] = extent.
xMinimum();
932 geoTransform[1] = pixelSize;
933 geoTransform[2] = 0.0;
934 geoTransform[3] = extent.
yMaximum();
935 geoTransform[4] = 0.0;
936 geoTransform[5] = -( extent.
height() / nRows );
943 return QString(
"%1.%2.tif" ).arg( outputInfo.fileName() ).arg( fileIndex );
949 return QString(
"%1.vrt" ).arg( outputInfo.fileName() );