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; }
QgsRasterBlock* QgsSingleBandGrayRenderer::block( int bandNo, QgsRectangle const & extent, int width, int height ) { Q_UNUSED( bandNo ); QgsDebugMsg( QString( "width = %1 height = %2" ).arg( width ).arg( height ) ); QgsRasterBlock *outputBlock = new QgsRasterBlock(); if ( !mInput ) { return outputBlock; } QgsRasterBlock *inputBlock = mInput->block( mGrayBand, extent, width, height ); if ( !inputBlock || inputBlock->isEmpty() ) { QgsDebugMsg( "No raster data!" ); delete inputBlock; return outputBlock; } QgsRasterBlock *alphaBlock = 0; if ( mAlphaBand > 0 && mGrayBand != mAlphaBand ) { alphaBlock = mInput->block( mAlphaBand, extent, width, height ); if ( !alphaBlock || alphaBlock->isEmpty() ) { // TODO: better to render without alpha delete inputBlock; delete alphaBlock; return outputBlock; } } else if ( mAlphaBand > 0 ) { alphaBlock = inputBlock; } if ( !outputBlock->reset( QGis::ARGB32_Premultiplied, width, height ) ) { delete inputBlock; delete alphaBlock; return outputBlock; } QRgb myDefaultColor = NODATA_COLOR; for ( qgssize i = 0; i < ( qgssize )width*height; i++ ) { if ( inputBlock->isNoData( i ) ) { outputBlock->setColor( i, myDefaultColor ); continue; } double grayVal = inputBlock->value( i ); double currentAlpha = mOpacity; if ( mRasterTransparency ) { currentAlpha = mRasterTransparency->alphaValue( grayVal, mOpacity * 255 ) / 255.0; } if ( mAlphaBand > 0 ) { currentAlpha *= alphaBlock->value( i ) / 255.0; } if ( mContrastEnhancement ) { if ( !mContrastEnhancement->isValueInDisplayableRange( grayVal ) ) { outputBlock->setColor( i, myDefaultColor ); continue; } grayVal = mContrastEnhancement->enhanceContrast( grayVal ); } if ( mGradient == WhiteToBlack ) { grayVal = 255 - grayVal; } if ( qgsDoubleNear( currentAlpha, 1.0 ) ) { outputBlock->setColor( i, qRgba( grayVal, grayVal, grayVal, 255 ) ); } else { outputBlock->setColor( i, qRgba( currentAlpha * grayVal, currentAlpha * grayVal, currentAlpha * grayVal, currentAlpha * 255 ) ); } } delete inputBlock; if ( mAlphaBand > 0 && mGrayBand != mAlphaBand ) { delete alphaBlock; } return outputBlock; }
QgsRasterBlock *QgsHillshadeRenderer::block( int bandNo, const QgsRectangle &extent, int width, int height, QgsRasterBlockFeedback* feedback ) { Q_UNUSED( bandNo ); QgsRasterBlock *outputBlock = new QgsRasterBlock(); if ( !mInput ) { QgsDebugMsg( "No input raster!" ); return outputBlock; } QgsRasterBlock *inputBlock = mInput->block( mBand, extent, width, height, feedback ); if ( !inputBlock || inputBlock->isEmpty() ) { QgsDebugMsg( "No raster data!" ); delete inputBlock; return outputBlock; } QgsRasterBlock *alphaBlock = nullptr; if ( mAlphaBand > 0 && mBand != mAlphaBand ) { alphaBlock = mInput->block( mAlphaBand, extent, width, height, feedback ); if ( !alphaBlock || alphaBlock->isEmpty() ) { // TODO: better to render without alpha delete inputBlock; delete alphaBlock; return outputBlock; } } else if ( mAlphaBand > 0 ) { alphaBlock = inputBlock; } if ( !outputBlock->reset( Qgis::ARGB32_Premultiplied, width, height ) ) { delete inputBlock; delete alphaBlock; return outputBlock; } double cellXSize = extent.width() / double( width ); double cellYSize = extent.height() / double( height ); double zenithRad = qMax( 0.0, 90 - mLightAngle ) * M_PI / 180.0; double azimuthRad = -1 * mLightAzimuth * M_PI / 180.0; double cosZenithRad = cos( zenithRad ); double sinZenithRad = sin( zenithRad ); // Multi direction hillshade: http://pubs.usgs.gov/of/1992/of92-422/of92-422.pdf double angle0Rad = ( -1 * mLightAzimuth - 45 - 45 * 0.5 ) * M_PI / 180.0; double angle1Rad = ( -1 * mLightAzimuth - 45 * 0.5 ) * M_PI / 180.0; double angle2Rad = ( -1 * mLightAzimuth + 45 * 0.5 ) * M_PI / 180.0; double angle3Rad = ( -1 * mLightAzimuth + 45 + 45 * 0.5 ) * M_PI / 180.0; QRgb myDefaultColor = NODATA_COLOR; for ( qgssize i = 0; i < ( qgssize )height; i++ ) { for ( qgssize j = 0; j < ( qgssize )width; j++ ) { if ( inputBlock->isNoData( i, j ) ) { outputBlock->setColor( i, j, myDefaultColor ); continue; } qgssize iUp, iDown, jLeft, jRight; if ( i == 0 ) { iUp = i; iDown = i + 1; } else if ( i < ( qgssize )height - 1 ) { iUp = i - 1; iDown = i + 1; } else { iUp = i - 1; iDown = i; } if ( j == 0 ) { jLeft = j; jRight = j + 1; } else if ( j < ( qgssize )width - 1 ) { jLeft = j - 1; jRight = j + 1; } else { jLeft = j - 1; jRight = j; } double x11; double x21; double x31; double x12; double x22; // Working cell double x32; double x13; double x23; double x33; // This is center cell. It is not nodata. Use this in place of nodata neighbors x22 = inputBlock->value( i, j ); x11 = inputBlock->isNoData( iUp, jLeft ) ? x22 : inputBlock->value( iUp, jLeft ); x21 = inputBlock->isNoData( i, jLeft ) ? x22 : inputBlock->value( i, jLeft ); x31 = inputBlock->isNoData( iDown, jLeft ) ? x22 : inputBlock->value( iDown, jLeft ); x12 = inputBlock->isNoData( iUp, j ) ? x22 : inputBlock->value( iUp, j ); // x22 x32 = inputBlock->isNoData( iDown, j ) ? x22 : inputBlock->value( iDown, j ); x13 = inputBlock->isNoData( iUp, jRight ) ? x22 : inputBlock->value( iUp, jRight ); x23 = inputBlock->isNoData( i, jRight ) ? x22 : inputBlock->value( i, jRight ); x33 = inputBlock->isNoData( iDown, jRight ) ? x22 : inputBlock->value( iDown, jRight ); double derX = calcFirstDerX( x11, x21, x31, x12, x22, x32, x13, x23, x33, cellXSize ); double derY = calcFirstDerY( x11, x21, x31, x12, x22, x32, x13, x23, x33, cellYSize ); double slopeRad = atan( mZFactor * sqrt( derX * derX + derY * derY ) ); double aspectRad = atan2( derX, -derY ); double grayValue; if ( !mMultiDirectional ) { // Standard single direction hillshade grayValue = qBound( 0.0, 255.0 * ( cosZenithRad * cos( slopeRad ) + sinZenithRad * sin( slopeRad ) * cos( azimuthRad - aspectRad ) ) , 255.0 ); } else { // Weighted multi direction as in http://pubs.usgs.gov/of/1992/of92-422/of92-422.pdf double weight0 = sin( aspectRad - angle0Rad ); double weight1 = sin( aspectRad - angle1Rad ); double weight2 = sin( aspectRad - angle2Rad ); double weight3 = sin( aspectRad - angle3Rad ); weight0 = weight0 * weight0; weight1 = weight1 * weight1; weight2 = weight2 * weight2; weight3 = weight3 * weight3; double cosSlope = cosZenithRad * cos( slopeRad ); double sinSlope = sinZenithRad * sin( slopeRad ); double color0 = cosSlope + sinSlope * cos( angle0Rad - aspectRad ) ; double color1 = cosSlope + sinSlope * cos( angle1Rad - aspectRad ) ; double color2 = cosSlope + sinSlope * cos( angle2Rad - aspectRad ) ; double color3 = cosSlope + sinSlope * cos( angle3Rad - aspectRad ) ; grayValue = qBound( 0.0, 255 * ( weight0 * color0 + weight1 * color1 + weight2 * color2 + weight3 * color3 ) * 0.5, 255.0 ); } double currentAlpha = mOpacity; if ( mRasterTransparency ) { currentAlpha = mRasterTransparency->alphaValue( x22, mOpacity * 255 ) / 255.0; } if ( mAlphaBand > 0 ) { currentAlpha *= alphaBlock->value( i ) / 255.0; } if ( qgsDoubleNear( currentAlpha, 1.0 ) ) { outputBlock->setColor( i, j, qRgba( grayValue, grayValue, grayValue, 255 ) ); } else { outputBlock->setColor( i, j, qRgba( currentAlpha * grayValue, currentAlpha * grayValue, currentAlpha * grayValue, currentAlpha * 255 ) ); } } } delete inputBlock; if ( mAlphaBand > 0 && mBand != mAlphaBand ) { delete alphaBlock; } return outputBlock; }
QgsRasterBlock* QgsSingleBandPseudoColorRenderer::block( int bandNo, QgsRectangle const & extent, int width, int height, QgsRasterBlockFeedback* feedback ) { Q_UNUSED( bandNo ); QgsRasterBlock *outputBlock = new QgsRasterBlock(); if ( !mInput || !mShader ) { return outputBlock; } QgsRasterBlock *inputBlock = mInput->block( mBand, extent, width, height, feedback ); if ( !inputBlock || inputBlock->isEmpty() ) { QgsDebugMsg( "No raster data!" ); delete inputBlock; return outputBlock; } //rendering is faster without considering user-defined transparency bool hasTransparency = usesTransparency(); QgsRasterBlock *alphaBlock = nullptr; if ( mAlphaBand > 0 && mAlphaBand != mBand ) { alphaBlock = mInput->block( mAlphaBand, extent, width, height, feedback ); if ( !alphaBlock || alphaBlock->isEmpty() ) { delete inputBlock; delete alphaBlock; return outputBlock; } } else if ( mAlphaBand == mBand ) { alphaBlock = inputBlock; } if ( !outputBlock->reset( Qgis::ARGB32_Premultiplied, width, height ) ) { delete inputBlock; delete alphaBlock; return outputBlock; } QRgb myDefaultColor = NODATA_COLOR; for ( qgssize i = 0; i < ( qgssize )width*height; i++ ) { if ( inputBlock->isNoData( i ) ) { outputBlock->setColor( i, myDefaultColor ); continue; } double val = inputBlock->value( i ); int red, green, blue, alpha; if ( !mShader->shade( val, &red, &green, &blue, &alpha ) ) { outputBlock->setColor( i, myDefaultColor ); continue; } if ( alpha < 255 ) { // Working with premultiplied colors, so multiply values by alpha red *= ( alpha / 255.0 ); blue *= ( alpha / 255.0 ); green *= ( alpha / 255.0 ); } if ( !hasTransparency ) { outputBlock->setColor( i, qRgba( red, green, blue, alpha ) ); } else { //opacity double currentOpacity = mOpacity; if ( mRasterTransparency ) { currentOpacity = mRasterTransparency->alphaValue( val, mOpacity * 255 ) / 255.0; } if ( mAlphaBand > 0 ) { currentOpacity *= alphaBlock->value( i ) / 255.0; } outputBlock->setColor( i, qRgba( currentOpacity * red, currentOpacity * green, currentOpacity * blue, currentOpacity * alpha ) ); } } delete inputBlock; if ( mAlphaBand > 0 && mBand != mAlphaBand ) { delete alphaBlock; } return outputBlock; }
QgsRasterBlock * QgsHueSaturationFilter::block( int bandNo, QgsRectangle const & extent, int width, int height, QgsRasterBlockFeedback* feedback ) { Q_UNUSED( bandNo ); QgsDebugMsgLevel( QString( "width = %1 height = %2 extent = %3" ).arg( width ).arg( height ).arg( extent.toString() ), 4 ); QgsRasterBlock *outputBlock = new QgsRasterBlock(); if ( !mInput ) { return outputBlock; } // At this moment we know that we read rendered image int bandNumber = 1; QgsRasterBlock *inputBlock = mInput->block( bandNumber, extent, width, height, feedback ); if ( !inputBlock || inputBlock->isEmpty() ) { QgsDebugMsg( "No raster data!" ); delete inputBlock; return outputBlock; } if ( mSaturation == 0 && mGrayscaleMode == GrayscaleOff && !mColorizeOn ) { QgsDebugMsgLevel( "No hue/saturation change.", 4 ); delete outputBlock; return inputBlock; } if ( !outputBlock->reset( Qgis::ARGB32_Premultiplied, width, height ) ) { delete inputBlock; return outputBlock; } // adjust image QRgb myNoDataColor = qRgba( 0, 0, 0, 0 ); QRgb myRgb; QColor myColor; int h, s, l; int r, g, b, alpha; double alphaFactor = 1.0; for ( qgssize i = 0; i < ( qgssize )width*height; i++ ) { if ( inputBlock->color( i ) == myNoDataColor ) { outputBlock->setColor( i, myNoDataColor ); continue; } myRgb = inputBlock->color( i ); myColor = QColor( myRgb ); // Alpha must be taken from QRgb, since conversion from QRgb->QColor loses alpha alpha = qAlpha( myRgb ); if ( alpha == 0 ) { // totally transparent, no changes required outputBlock->setColor( i, myRgb ); continue; } // Get rgb for color myColor.getRgb( &r, &g, &b ); if ( alpha != 255 ) { // Semi-transparent pixel. We need to adjust the colors since we are using Qgis::ARGB32_Premultiplied // and color values have been premultiplied by alpha alphaFactor = alpha / 255.; r /= alphaFactor; g /= alphaFactor; b /= alphaFactor; myColor = QColor::fromRgb( r, g, b ); } myColor.getHsl( &h, &s, &l ); // Changing saturation? if (( mGrayscaleMode != GrayscaleOff ) || ( mSaturationScale != 1 ) ) { processSaturation( r, g, b, h, s, l ); } // Colorizing? if ( mColorizeOn ) { processColorization( r, g, b, h, s, l ); } // Convert back to rgb if ( alpha != 255 ) { // Transparent pixel, need to premultiply color components r *= alphaFactor; g *= alphaFactor; b *= alphaFactor; } outputBlock->setColor( i, qRgba( r, g, b, alpha ) ); } delete inputBlock; return outputBlock; }
QgsRasterBlock * QgsBrightnessContrastFilter::block( int bandNo, QgsRectangle const & extent, int width, int height ) { Q_UNUSED( bandNo ); QgsDebugMsg( QString( "width = %1 height = %2 extent = %3" ).arg( width ).arg( height ).arg( extent.toString() ) ); QgsRasterBlock *outputBlock = new QgsRasterBlock(); if ( !mInput ) { return outputBlock; } // At this moment we know that we read rendered image int bandNumber = 1; QgsRasterBlock *inputBlock = mInput->block( bandNumber, extent, width, height ); if ( !inputBlock || inputBlock->isEmpty() ) { QgsDebugMsg( "No raster data!" ); delete inputBlock; return outputBlock; } if ( mBrightness == 0 && mContrast == 0 ) { QgsDebugMsg( "No brightness changes." ); delete outputBlock; return inputBlock; } if ( !outputBlock->reset( QGis::ARGB32_Premultiplied, width, height ) ) { delete inputBlock; return outputBlock; } // adjust image QRgb myNoDataColor = qRgba( 0, 0, 0, 0 ); QRgb myColor; int r, g, b, alpha; double f = qPow(( mContrast + 100 ) / 100.0, 2 ); for ( qgssize i = 0; i < ( qgssize )width*height; i++ ) { if ( inputBlock->color( i ) == myNoDataColor ) { outputBlock->setColor( i, myNoDataColor ); continue; } myColor = inputBlock->color( i ); alpha = qAlpha( myColor ); r = adjustColorComponent( qRed( myColor ), alpha, mBrightness, f ); g = adjustColorComponent( qGreen( myColor ), alpha, mBrightness, f ); b = adjustColorComponent( qBlue( myColor ), alpha, mBrightness, f ); outputBlock->setColor( i, qRgba( r, g, b, alpha ) ); } delete inputBlock; return outputBlock; }
QgsRasterBlock *QgsHillshadeRenderer::block( int bandNo, const QgsRectangle &extent, int width, int height ) { Q_UNUSED( bandNo ); QgsRasterBlock *outputBlock = new QgsRasterBlock(); if ( !mInput ) { QgsDebugMsg( "No input raster!" ); return outputBlock; } QgsRasterBlock *inputBlock = mInput->block( mBand, extent, width, height ); if ( !inputBlock || inputBlock->isEmpty() ) { QgsDebugMsg( "No raster data!" ); delete inputBlock; return outputBlock; } if ( !outputBlock->reset( QGis::ARGB32_Premultiplied, width, height ) ) { delete inputBlock; return outputBlock; } double cellXSize = extent.width() / double( width ); double cellYSize = extent.height() / double( height ); double zenithRad = qMax( 0.0, 90 - mLightAngle ) * M_PI / 180.0; double azimuthRad = -1 * mLightAzimuth * M_PI / 180.0; double cosZenithRad = cos( zenithRad ); double sinZenithRad = sin( zenithRad ); QRgb myDefaultColor = NODATA_COLOR; for ( qgssize i = 0; i < ( qgssize )height; i++ ) { for ( qgssize j = 0; j < ( qgssize )width; j++ ) { if ( inputBlock->isNoData( i, j ) ) { outputBlock->setColor( i, j, myDefaultColor ); continue; } qgssize iUp, iDown, jLeft, jRight; if ( i == 0 ) { iUp = i; iDown = i + 1; } else if ( i < ( qgssize )height - 1 ) { iUp = i - 1; iDown = i + 1; } else { iUp = i - 1; iDown = i; } if ( j == 0 ) { jLeft = j; jRight = j + 1; } else if ( j < ( qgssize )width - 1 ) { jLeft = j - 1; jRight = j + 1; } else { jLeft = j - 1; jRight = j; } double x11; double x21; double x31; double x12; double x22; // Working cell double x32; double x13; double x23; double x33; // This is center cell. It is not nodata. Use this in place of nodata neighbors x22 = inputBlock->value( i, j ); x11 = inputBlock->isNoData( iUp, jLeft ) ? x22 : inputBlock->value( iUp, jLeft ); x21 = inputBlock->isNoData( i, jLeft ) ? x22 : inputBlock->value( i, jLeft ); x31 = inputBlock->isNoData( iDown, jLeft ) ? x22 : inputBlock->value( iDown, jLeft ); x12 = inputBlock->isNoData( iUp, j ) ? x22 : inputBlock->value( iUp, j ); // x22 x32 = inputBlock->isNoData( iDown, j ) ? x22 : inputBlock->value( iDown, j ); x13 = inputBlock->isNoData( iUp, jRight ) ? x22 : inputBlock->value( iUp, jRight ); x23 = inputBlock->isNoData( i, jRight ) ? x22 : inputBlock->value( i, jRight ); x33 = inputBlock->isNoData( iDown, jRight ) ? x22 : inputBlock->value( iDown, jRight ); double derX = calcFirstDerX( x11, x21, x31, x12, x22, x32, x13, x23, x33, cellXSize ); double derY = calcFirstDerY( x11, x21, x31, x12, x22, x32, x13, x23, x33, cellYSize ); double slope_rad = atan( mZFactor * sqrt( derX * derX + derY * derY ) ); double aspectRad = atan2( derX, -derY ); double colorvalue = qBound( 0.0, 255.0 * (( cosZenithRad * cos( slope_rad ) ) + ( sinZenithRad * sin( slope_rad ) * cos( azimuthRad - aspectRad ) ) ), 255.0 ); outputBlock->setColor( i, j, qRgb( colorvalue, colorvalue, colorvalue ) ); } } return outputBlock; }