QgsRasterBlock* QgsSingleBandColorDataRenderer::block( int bandNo, QgsRectangle const & extent, int width, int height, QgsRasterBlockFeedback* feedback ) { Q_UNUSED( bandNo ); QgsRasterBlock *outputBlock = new QgsRasterBlock(); if ( !mInput ) { return outputBlock; } QgsRasterBlock *inputBlock = mInput->block( mBand, extent, width, height, feedback ); if ( !inputBlock || inputBlock->isEmpty() ) { QgsDebugMsg( "No raster data!" ); delete inputBlock; return outputBlock; } bool hasTransparency = usesTransparency(); if ( !hasTransparency ) { // Nothing to do, just retype if necessary inputBlock->convert( Qgis::ARGB32_Premultiplied ); delete outputBlock; return inputBlock; } if ( !outputBlock->reset( Qgis::ARGB32_Premultiplied, width, height ) ) { delete inputBlock; return outputBlock; } // make sure input is also premultiplied! inputBlock->convert( Qgis::ARGB32_Premultiplied ); QRgb* inputBits = ( QRgb* )inputBlock->bits(); QRgb* outputBits = ( QRgb* )outputBlock->bits(); for ( qgssize i = 0; i < ( qgssize )width*height; i++ ) { QRgb c = inputBits[i]; outputBits[i] = qRgba( mOpacity * qRed( c ), mOpacity * qGreen( c ), mOpacity * qBlue( c ), mOpacity * qAlpha( c ) ); } delete inputBlock; return outputBlock; }
QgsRasterBlock* QgsSingleBandColorDataRenderer::block( int bandNo, QgsRectangle const & extent, int width, int height ) { Q_UNUSED( bandNo ); QgsRasterBlock *outputBlock = new QgsRasterBlock(); if ( !mInput ) { return outputBlock; } QgsRasterBlock *inputBlock = mInput->block( mBand, extent, width, height ); if ( !inputBlock || inputBlock->isEmpty() ) { QgsDebugMsg( "No raster data!" ); delete inputBlock; return outputBlock; } bool hasTransparency = usesTransparency(); if ( !hasTransparency ) { // Nothing to do, just retype if necessary inputBlock->convert( QgsRasterBlock::ARGB32_Premultiplied ); delete outputBlock; return inputBlock; } if ( !outputBlock->reset( QgsRasterBlock::ARGB32_Premultiplied, width, height ) ) { delete inputBlock; return outputBlock; } for ( size_t i = 0; i < ( size_t )width*height; i++ ) { QRgb pixelColor; double alpha = 255.0; QRgb c = inputBlock->color( i ); alpha = qAlpha( c ); pixelColor = qRgba( mOpacity * qRed( c ), mOpacity * qGreen( c ), mOpacity * qBlue( c ), mOpacity * alpha ); outputBlock->setColor( i, pixelColor ); } delete inputBlock; return outputBlock; }
static QByteArray _readDtmData( QgsRasterDataProvider *provider, const QgsRectangle &extent, int res ) { QElapsedTimer t; t.start(); // TODO: use feedback object? (but GDAL currently does not support cancelation anyway) QgsRasterBlock *block = provider->block( 1, extent, res, res ); QByteArray data; if ( block ) { block->convert( Qgis::Float32 ); // currently we expect just floats data = block->data(); data.detach(); // this should make a deep copy delete block; } return data; }
float QgsDemHeightMapGenerator::heightAt( double x, double y ) { // TODO: this is quite a primitive implementation: better to use heightmaps currently in use int res = 1024; QgsRectangle rect = mDtm->extent(); if ( mDtmCoarseData.isEmpty() ) { QgsRasterBlock *block = mDtm->dataProvider()->block( 1, rect, res, res ); block->convert( Qgis::Float32 ); mDtmCoarseData = block->data(); mDtmCoarseData.detach(); // make a deep copy delete block; } int cellX = ( int )( ( x - rect.xMinimum() ) / rect.width() * res + .5f ); int cellY = ( int )( ( rect.yMaximum() - y ) / rect.height() * res + .5f ); cellX = qBound( 0, cellX, res - 1 ); cellY = qBound( 0, cellY, res - 1 ); const float *data = ( const float * ) mDtmCoarseData.constData(); return data[cellX + cellY * res]; }
QByteArray QgsDemHeightMapGenerator::renderSynchronously( int x, int y, int z ) { // extend the rect by half-pixel on each side? to get the values in "corners" QgsRectangle extent = mTilingScheme.tileToExtent( x, y, z ); float mapUnitsPerPixel = extent.width() / mResolution; extent.grow( mapUnitsPerPixel / 2 ); // but make sure not to go beyond the full extent (returns invalid values) QgsRectangle fullExtent = mTilingScheme.tileToExtent( 0, 0, 0 ); extent = extent.intersect( &fullExtent ); QgsRasterBlock *block = mDtm->dataProvider()->block( 1, extent, mResolution, mResolution ); QByteArray data; if ( block ) { block->convert( Qgis::Float32 ); // currently we expect just floats data = block->data(); data.detach(); // this should make a deep copy delete block; } return data; }
int QgsGrassGisLib::readRasterRow( int fd, void * buf, int row, RASTER_MAP_TYPE data_type, bool noDataAsZero ) { if ( row < 0 || row >= mRows ) { QgsDebugMsg( QString( "row %1 out of range 0 - %2" ).arg( row ).arg( mRows ) ); return 0; } // TODO: use cached block with more rows Raster raster = mRasters.value( fd ); //if ( !raster.provider ) return -1; if ( !raster.input ) return -1; // Create extent for current row QgsRectangle blockRect = mExtent; double yRes = mExtent.height() / mRows; double yMax = mExtent.yMaximum() - yRes * row; //QgsDebugMsg( QString( "height = %1 mRows = %2" ).arg( mExtent.height() ).arg( mRows ) ); //QgsDebugMsg( QString( "row = %1 yRes = %2 yRes * row = %3" ).arg( row ).arg( yRes ).arg( yRes * row ) ); //QgsDebugMsg( QString( "mExtent.yMaximum() = %1 yMax = %2" ).arg( mExtent.yMaximum() ).arg( yMax ) ); blockRect.setYMaximum( yMax ); blockRect.setYMinimum( yMax - yRes ); QgsRasterBlock *block = raster.input->block( raster.band, blockRect, mColumns, 1 ); if ( !block ) return -1; QGis::DataType requestedType = qgisRasterType( data_type ); //QgsDebugMsg( QString("data_type = %1").arg(data_type) ); //QgsDebugMsg( QString("requestedType = %1").arg(requestedType) ); //QgsDebugMsg( QString("requestedType size = %1").arg( QgsRasterBlock::typeSize( requestedType ) ) ); //QgsDebugMsg( QString("block->dataType = %1").arg( block->dataType() ) ); block->convert( requestedType ); memcpy( buf, block->bits( 0 ), QgsRasterBlock::typeSize( requestedType ) * mColumns ); for ( int i = 0; i < mColumns; i++ ) { QgsDebugMsgLevel( QString( "row = %1 i = %2 val = %3 isNoData = %4" ).arg( row ).arg( i ).arg( block->value( i ) ).arg( block->isNoData( i ) ), 5 ); //(( CELL * ) buf )[i] = i; if ( block->isNoData( 0, i ) ) { if ( noDataAsZero ) { switch ( data_type ) { case CELL_TYPE: G_zero(( char * ) &(( CELL * ) buf )[i], G_raster_size( data_type ) ); break; case FCELL_TYPE: G_zero(( char * ) &(( FCELL * ) buf )[i], G_raster_size( data_type ) ); break; case DCELL_TYPE: G_zero(( char * ) &(( DCELL * ) buf )[i], G_raster_size( data_type ) ); break; default: break; } } else { switch ( data_type ) { case CELL_TYPE: G_set_c_null_value( &(( CELL * ) buf )[i], 1 ); break; case FCELL_TYPE: G_set_f_null_value( &(( FCELL * ) buf )[i], 1 ); break; case DCELL_TYPE: G_set_d_null_value( &(( DCELL * ) buf )[i], 1 ); break; default: break; } } } //else //{ //memcpy( &( buf[i] ), block->bits( 0, i ), 4 ); //buf[i] = (int) block->value( 0, i); //QgsDebugMsg( QString("buf[i] = %1").arg(buf[i])); //} } delete block; return 1; }
bool QgsGrassRasterImport::import() { QgsDebugMsg( "entered" ); if ( !mPipe ) { setError( "Pipe is null." ); return false; } QgsRasterDataProvider * provider = mPipe->provider(); if ( !provider ) { setError( "Pipe has no provider." ); return false; } if ( !provider->isValid() ) { setError( "Provider is not valid." ); return false; } int redBand = 0; int greenBand = 0; int blueBand = 0; for ( int band = 1; band <= provider->bandCount(); band++ ) { QgsDebugMsg( QString( "band = %1" ).arg( band ) ); int colorInterpretation = provider->colorInterpretation( band ); if ( colorInterpretation == QgsRaster::RedBand ) { redBand = band; } else if ( colorInterpretation == QgsRaster::GreenBand ) { greenBand = band; } else if ( colorInterpretation == QgsRaster::BlueBand ) { blueBand = band; } QGis::DataType qgis_out_type = QGis::UnknownDataType; RASTER_MAP_TYPE data_type = -1; switch ( provider->dataType( band ) ) { case QGis::Byte: case QGis::UInt16: case QGis::Int16: case QGis::UInt32: case QGis::Int32: qgis_out_type = QGis::Int32; break; case QGis::Float32: qgis_out_type = QGis::Float32; break; case QGis::Float64: qgis_out_type = QGis::Float64; break; case QGis::ARGB32: case QGis::ARGB32_Premultiplied: qgis_out_type = QGis::Int32; // split to multiple bands? break; case QGis::CInt16: case QGis::CInt32: case QGis::CFloat32: case QGis::CFloat64: case QGis::UnknownDataType: setError( tr( "Data type %1 not supported" ).arg( provider->dataType( band ) ) ); return false; } QgsDebugMsg( QString( "data_type = %1" ).arg( data_type ) ); QString module = QgsGrass::qgisGrassModulePath() + "/qgis.r.in"; QStringList arguments; QString name = mGrassObject.name(); if ( provider->bandCount() > 1 ) { // raster.<band> to keep in sync with r.in.gdal name += QString( ".%1" ).arg( band ); } arguments.append( "output=" + name ); // get list of all output names QTemporaryFile gisrcFile; QProcess* process = 0; try { process = QgsGrass::startModule( mGrassObject.gisdbase(), mGrassObject.location(), mGrassObject.mapset(), module, arguments, gisrcFile ); } catch ( QgsGrass::Exception &e ) { setError( e.what() ); return false; } QDataStream outStream( process ); outStream << mExtent << ( qint32 )mXSize << ( qint32 )mYSize; outStream << ( qint32 )qgis_out_type; // calculate reasonable block size (5MB) int maximumTileHeight = 5000000 / mXSize; maximumTileHeight = std::max( 1, maximumTileHeight ); // smaller if reprojecting so that it can be canceled quickly if ( mPipe->projector() ) { maximumTileHeight = std::max( 1, 100000 / mXSize ); } QgsRasterIterator iter( mPipe->last() ); iter.setMaximumTileWidth( mXSize ); iter.setMaximumTileHeight( maximumTileHeight ); iter.startRasterRead( band, mXSize, mYSize, mExtent ); int iterLeft = 0; int iterTop = 0; int iterCols = 0; int iterRows = 0; QgsRasterBlock* block = 0; process->setReadChannel( QProcess::StandardOutput ); while ( iter.readNextRasterPart( band, iterCols, iterRows, &block, iterLeft, iterTop ) ) { for ( int row = 0; row < iterRows; row++ ) { if ( !block->convert( qgis_out_type ) ) { setError( tr( "Cannot convert block (%1) to data type %2" ).arg( block->toString() ).arg( qgis_out_type ) ); delete block; return false; } // prepare null values double noDataValue; if ( block->hasNoDataValue() ) { noDataValue = block->noDataValue(); } else { switch ( qgis_out_type ) { case QGis::Int32: noDataValue = -2147483648.0; break; case QGis::Float32: noDataValue = std::numeric_limits<float>::max() * -1.0; break; case QGis::Float64: noDataValue = std::numeric_limits<double>::max() * -1.0; break; default: // should not happen noDataValue = std::numeric_limits<double>::max() * -1.0; } for ( qgssize i = 0; i < ( qgssize )block->width()*block->height(); i++ ) { if ( block->isNoData( i ) ) { block->setValue( i, noDataValue ); } } } char * data = block->bits( row, 0 ); int size = iterCols * block->dataTypeSize(); QByteArray byteArray = QByteArray::fromRawData( data, size ); // does not copy data and does not take ownership if ( isCanceled() ) { outStream << true; // cancel module break; } outStream << false; // not canceled outStream << noDataValue; outStream << byteArray; // Without waitForBytesWritten() it does not finish ok on Windows (process timeout) process->waitForBytesWritten( -1 ); #ifndef Q_OS_WIN // wait until the row is written to allow quick cancel (don't send data to buffer) process->waitForReadyRead(); bool result; outStream >> result; #endif } delete block; if ( isCanceled() ) { outStream << true; // cancel module break; } } // TODO: send something back from module and read it here to close map correctly in module process->closeWriteChannel(); // TODO: best timeout? process->waitForFinished( 30000 ); QString stdoutString = process->readAllStandardOutput().data(); QString stderrString = process->readAllStandardError().data(); QString processResult = QString( "exitStatus=%1, exitCode=%2, error=%3, errorString=%4 stdout=%5, stderr=%6" ) .arg( process->exitStatus() ).arg( process->exitCode() ) .arg( process->error() ).arg( process->errorString() ) .arg( stdoutString.replace( "\n", ", " ) ).arg( stderrString.replace( "\n", ", " ) ); QgsDebugMsg( "processResult: " + processResult ); if ( process->exitStatus() != QProcess::NormalExit ) { setError( process->errorString() ); delete process; return false; } if ( process->exitCode() != 0 ) { setError( stderrString ); delete process; return false; } delete process; } QgsDebugMsg( QString( "redBand = %1 greenBand = %2 blueBand = %3" ).arg( redBand ).arg( greenBand ).arg( blueBand ) ); if ( redBand > 0 && greenBand > 0 && blueBand > 0 ) { // TODO: check if the group exists // I_find_group() QString name = mGrassObject.name(); G_TRY { QgsGrass::setMapset( mGrassObject.gisdbase(), mGrassObject.location(), mGrassObject.mapset() ); struct Ref ref; I_get_group_ref( name.toUtf8().data(), &ref ); QString redName = name + QString( ".%1" ).arg( redBand ); QString greenName = name + QString( ".%1" ).arg( greenBand ); QString blueName = name + QString( ".%1" ).arg( blueBand ); I_add_file_to_group_ref( redName.toUtf8().data(), mGrassObject.mapset().toUtf8().data(), &ref ); I_add_file_to_group_ref( greenName.toUtf8().data(), mGrassObject.mapset().toUtf8().data(), &ref ); I_add_file_to_group_ref( blueName.toUtf8().data(), mGrassObject.mapset().toUtf8().data(), &ref ); I_put_group_ref( name.toUtf8().data(), &ref ); } G_CATCH( QgsGrass::Exception &e ) { QgsDebugMsg( QString( "Cannot create group: %1" ).arg( e.what() ) ); }