[QGIS Commit] r12809 - trunk/qgis/src/core/raster
svn_qgis at osgeo.org
svn_qgis at osgeo.org
Thu Jan 21 04:23:18 EST 2010
Author: mhugent
Date: 2010-01-21 04:23:15 -0500 (Thu, 21 Jan 2010)
New Revision: 12809
Modified:
trunk/qgis/src/core/raster/qgsrasterlayer.cpp
trunk/qgis/src/core/raster/qgsrasterlayer.h
Log:
Draw GDAL rasters and WMS layers in several parts if they contain many pixels (e.g. when printing in high resolution to large paper sizes)
Modified: trunk/qgis/src/core/raster/qgsrasterlayer.cpp
===================================================================
--- trunk/qgis/src/core/raster/qgsrasterlayer.cpp 2010-01-20 22:40:19 UTC (rev 12808)
+++ trunk/qgis/src/core/raster/qgsrasterlayer.cpp 2010-01-21 09:23:15 UTC (rev 12809)
@@ -248,6 +248,7 @@
GDALClose( mGdalDataset );
}
}
+ delete mRasterShader;
}
@@ -1536,7 +1537,7 @@
//the drawable area can start to get very very large when you get down displaying 2x2 or smaller, this is becasue
//theQgsMapToPixel.mapUnitsPerPixel() is less then 1,
//so we will just get the pixel data and then render these special cases differently in paintImageToCanvas()
- if( 2 >= myRasterViewPort->clippedWidth && 2 >= myRasterViewPort->clippedHeight )
+ if ( 2 >= myRasterViewPort->clippedWidth && 2 >= myRasterViewPort->clippedHeight )
{
myRasterViewPort->drawableAreaXDim = myRasterViewPort->clippedWidth;
myRasterViewPort->drawableAreaYDim = myRasterViewPort->clippedHeight;
@@ -1591,90 +1592,88 @@
mDataProvider->setDpi( rendererContext.rasterScaleFactor() * 25.4 * rendererContext.scaleFactor() );
- QImage* image =
- mDataProvider->draw(
- myRasterExtent,
- // Below should calculate to the actual pixel size of the
- // part of the layer that's visible.
- static_cast<int>( fabs(( myRasterViewPort->clippedXMax - myRasterViewPort->clippedXMin )
- / theQgsMapToPixel.mapUnitsPerPixel() * mGeoTransform[1] ) + 1 ),
- static_cast<int>( fabs(( myRasterViewPort->clippedYMax - myRasterViewPort->clippedYMin )
- / theQgsMapToPixel.mapUnitsPerPixel() * mGeoTransform[5] ) + 1 )
-// myRasterViewPort->drawableAreaXDim,
-// myRasterViewPort->drawableAreaYDim
- );
+ //fetch image in several parts if it is too memory consuming
+ //also some WMS servers have a pixel limit, so it's better to make several requests
+ int totalPixelWidth = fabs(( myRasterViewPort->clippedXMax - myRasterViewPort->clippedXMin )
+ / theQgsMapToPixel.mapUnitsPerPixel() * mGeoTransform[1] ) + 1;
+ int totalPixelHeight = fabs(( myRasterViewPort->clippedYMax - myRasterViewPort->clippedYMin )
+ / theQgsMapToPixel.mapUnitsPerPixel() * mGeoTransform[5] ) + 1;
+ int numParts = totalPixelWidth * totalPixelHeight / 5000000 + 1.0;
+ int numRowsPerPart = totalPixelHeight / numParts + 1.0;
- if ( !image )
+
+ int currentPixelOffsetY = 0; //top y-coordinate of current raster part
+ //the width of a WMS image part
+ int pixelWidth = ( myRasterExtent.xMaximum() - myRasterExtent.xMinimum() ) / theQgsMapToPixel.mapUnitsPerPixel();
+ for ( int i = 0; i < numParts; ++i )
{
- // An error occurred.
- mErrorCaption = mDataProvider->lastErrorTitle();
- mError = mDataProvider->lastError();
+ //fetch a small overlap of 2 pixels between two adjacent tiles to avoid white stripes
+ QgsRectangle rasterPartRect( myRasterExtent.xMinimum(), myRasterExtent.yMaximum() - ( currentPixelOffsetY + numRowsPerPart + 2 ) * theQgsMapToPixel.mapUnitsPerPixel(), \
+ myRasterExtent.xMaximum(), myRasterExtent.yMaximum() - currentPixelOffsetY * theQgsMapToPixel.mapUnitsPerPixel() );
- delete myRasterViewPort;
- return FALSE;
- }
+ int pixelHeight = rasterPartRect.height() / theQgsMapToPixel.mapUnitsPerPixel();
+ QImage* image = mDataProvider->draw( rasterPartRect, pixelWidth, pixelHeight );
- QgsDebugMsg( "Done mDataProvider->draw." );
- QgsDebugMsg( "image stats: " );
+ if ( !image )
+ {
+ // An error occurred.
+ mErrorCaption = mDataProvider->lastErrorTitle();
+ mError = mDataProvider->lastError();
- QgsDebugMsg( QString( "depth=%1" ).arg( image->depth() ) );
- QgsDebugMsg( QString( "bytes=%1" ).arg( image->numBytes() ) );
- QgsDebugMsg( QString( "width=%1" ).arg( image->width() ) );
- QgsDebugMsg( QString( "height=%1" ).arg( image->height() ) );
+ delete myRasterViewPort;
+ return FALSE;
+ }
- QgsDebugMsg( "Want to theQPainter->drawImage with" );
+ QgsDebugMsg( "Done mDataProvider->draw." );
+ QgsDebugMsg( "image stats: " );
- QgsDebugMsg( QString( "origin x: %1" ).arg( myRasterViewPort->topLeftPoint.x() ) );
- QgsDebugMsg( QString( "(int)origin x: %1" ).arg( static_cast<int>( myRasterViewPort->topLeftPoint.x() ) ) );
- QgsDebugMsg( QString( "origin y: %1" ).arg( myRasterViewPort->topLeftPoint.y() ) );
- QgsDebugMsg( QString( "(int)origin y: %1" ).arg( static_cast<int>( myRasterViewPort->topLeftPoint.y() ) ) );
+ QgsDebugMsg( QString( "depth=%1" ).arg( image->depth() ) );
+ QgsDebugMsg( QString( "bytes=%1" ).arg( image->numBytes() ) );
+ QgsDebugMsg( QString( "width=%1" ).arg( image->width() ) );
+ QgsDebugMsg( QString( "height=%1" ).arg( image->height() ) );
- //Set the transparency for the whole layer
- //QImage::setAlphaChannel does not work quite as expected so set each pixel individually
- //Currently this is only done for WMS images, which should be small enough not to impact performance
+ QgsDebugMsg( "Want to theQPainter->drawImage with" );
- if ( mTransparencyLevel != 255 ) //improve performance if layer transparency not altered
- {
- QImage* transparentImageCopy = new QImage( *image ); //copy image if there is user transparency
- image = transparentImageCopy;
- int myWidth = image->width();
- int myHeight = image->height();
- QRgb myRgb;
- int newTransparency;
- for ( int myHeightRunner = 0; myHeightRunner < myHeight; myHeightRunner++ )
+ QgsDebugMsg( QString( "origin x: %1" ).arg( myRasterViewPort->topLeftPoint.x() ) );
+ QgsDebugMsg( QString( "(int)origin x: %1" ).arg( static_cast<int>( myRasterViewPort->topLeftPoint.x() ) ) );
+ QgsDebugMsg( QString( "origin y: %1" ).arg( myRasterViewPort->topLeftPoint.y() ) );
+ QgsDebugMsg( QString( "(int)origin y: %1" ).arg( static_cast<int>( myRasterViewPort->topLeftPoint.y() ) ) );
+
+ //Set the transparency for the whole layer
+ //QImage::setAlphaChannel does not work quite as expected so set each pixel individually
+ //Currently this is only done for WMS images, which should be small enough not to impact performance
+
+ if ( mTransparencyLevel != 255 ) //improve performance if layer transparency not altered
{
- QRgb* myLineBuffer = ( QRgb* ) transparentImageCopy->scanLine( myHeightRunner );
- for ( int myWidthRunner = 0; myWidthRunner < myWidth; myWidthRunner++ )
+ QImage* transparentImageCopy = new QImage( *image ); //copy image if there is user transparency
+ image = transparentImageCopy;
+ int myWidth = image->width();
+ int myHeight = image->height();
+ QRgb myRgb;
+ int newTransparency;
+ for ( int myHeightRunner = 0; myHeightRunner < myHeight; myHeightRunner++ )
{
- myRgb = image->pixel( myWidthRunner, myHeightRunner );
- //combine transparency from WMS and layer transparency
- newTransparency = ( double ) mTransparencyLevel / 255.0 * ( double )( qAlpha( myRgb ) );
- myLineBuffer[ myWidthRunner ] = qRgba( qRed( myRgb ), qGreen( myRgb ), qBlue( myRgb ), newTransparency );
+ QRgb* myLineBuffer = ( QRgb* ) transparentImageCopy->scanLine( myHeightRunner );
+ for ( int myWidthRunner = 0; myWidthRunner < myWidth; myWidthRunner++ )
+ {
+ myRgb = image->pixel( myWidthRunner, myHeightRunner );
+ //combine transparency from WMS and layer transparency
+ newTransparency = ( double ) mTransparencyLevel / 255.0 * ( double )( qAlpha( myRgb ) );
+ myLineBuffer[ myWidthRunner ] = qRgba( qRed( myRgb ), qGreen( myRgb ), qBlue( myRgb ), newTransparency );
+ }
}
}
- }
- // Since GDAL's RasterIO can't handle floating point, we have to round to
- // the nearest pixel. Add 0.5 to get rounding instead of truncation
- // out of static_cast<int>.
- theQPainter->drawImage( static_cast<int>(
- myRasterViewPort->topLeftPoint.x()
- + 0.5 // try simulating rounding instead of truncation, to avoid off-by-one errors
- // TODO: Check for rigorous correctness
- ),
- static_cast<int>(
- myRasterViewPort->topLeftPoint.y()
- + 0.5 // try simulating rounding instead of truncation, to avoid off-by-one errors
- // TODO: Check for rigorous correctness
- ),
- *image );
+ theQPainter->drawImage( myRasterViewPort->topLeftPoint.x(), myRasterViewPort->topLeftPoint.y() + currentPixelOffsetY, *image );
+ currentPixelOffsetY += numRowsPerPart;
- if ( mTransparencyLevel != 255 )
- {
- delete image;
+ if ( mTransparencyLevel != 255 )
+ {
+ delete image;
+ }
+
+ emit statusChanged( tr( "%1 retrieved using %2" ).arg( name() ).arg( mProviderKey ) );
}
-
- emit statusChanged( tr( "%1 retrieved using %2" ).arg( name() ).arg( mProviderKey ) );
}
else
{
@@ -4329,6 +4328,7 @@
{
return;
}
+
GDALRasterBandH myGdalRedBand = GDALGetRasterBand( mGdalDataset, myRedBandNo );
GDALRasterBandH myGdalGreenBand = GDALGetRasterBand( mGdalDataset, myGreenBandNo );
GDALRasterBandH myGdalBlueBand = GDALGetRasterBand( mGdalDataset, myBlueBandNo );
@@ -4337,26 +4337,19 @@
GDALDataType myGreenType = GDALGetRasterDataType( myGdalGreenBand );
GDALDataType myBlueType = GDALGetRasterDataType( myGdalBlueBand );
- void *myGdalRedData = readData( myGdalRedBand, theRasterViewPort );
- void *myGdalGreenData = readData( myGdalGreenBand, theRasterViewPort );
- void *myGdalBlueData = readData( myGdalBlueBand, theRasterViewPort );
+ QRgb* redImageScanLine = 0;
+ void* redRasterScanLine = 0;
+ QRgb* greenImageScanLine = 0;
+ void* greenRasterScanLine = 0;
+ QRgb* blueImageScanLine = 0;
+ void* blueRasterScanLine = 0;
- /* Check for out of memory error */
- if ( myGdalRedData == NULL || myGdalGreenData == NULL || myGdalBlueData == NULL )
- {
- // Safe to free NULL-pointer */
- VSIFree( myGdalRedData );
- VSIFree( myGdalGreenData );
- VSIFree( myGdalBlueData );
- return;
- }
-
- QImage myQImage = QImage( theRasterViewPort->drawableAreaXDim, theRasterViewPort->drawableAreaYDim, QImage::Format_ARGB32 );
QRgb myDefaultColor = qRgba( 255, 255, 255, 0 );
QgsRasterBandStats myRedBandStats;
QgsRasterBandStats myGreenBandStats;
QgsRasterBandStats myBlueBandStats;
+
/*
* If a stetch is requested and there are no user defined Min Max values
* we need to get these values from the bands themselves.
@@ -4408,35 +4401,40 @@
QgsContrastEnhancement* myGreenContrastEnhancement = contrastEnhancement( myGreenBandNo );
QgsContrastEnhancement* myBlueContrastEnhancement = contrastEnhancement( myBlueBandNo );
- QgsDebugMsg( "Starting main render loop" );
- for ( int myRow = 0; myRow < theRasterViewPort->drawableAreaYDim; ++myRow )
+ QgsRasterImageBuffer redImageBuffer( myGdalRedBand, theQPainter, theRasterViewPort, theQgsMapToPixel, &mGeoTransform[0] );
+ redImageBuffer.reset();
+ QgsRasterImageBuffer greenImageBuffer( myGdalGreenBand, theQPainter, theRasterViewPort, theQgsMapToPixel, &mGeoTransform[0] );
+ greenImageBuffer.setWritingEnabled( false ); //only draw to redImageBuffer
+ greenImageBuffer.reset();
+ QgsRasterImageBuffer blueImageBuffer( myGdalGreenBand, theQPainter, theRasterViewPort, theQgsMapToPixel, &mGeoTransform[0] );
+ blueImageBuffer.setWritingEnabled( false ); //only draw to redImageBuffer
+ blueImageBuffer.reset();
+
+ while ( redImageBuffer.nextScanLine( &redImageScanLine, &redRasterScanLine ) && greenImageBuffer.nextScanLine( &greenImageScanLine, &greenRasterScanLine ) \
+ && blueImageBuffer.nextScanLine( &blueImageScanLine, &blueRasterScanLine ) )
{
- QRgb* myLineBuffer = ( QRgb* )myQImage.scanLine( myRow );
- for ( int myColumn = 0; myColumn < theRasterViewPort->drawableAreaXDim; ++myColumn )
+ for ( int i = 0; i < theRasterViewPort->drawableAreaXDim; ++i )
{
- myRedValue = readValue( myGdalRedData, ( GDALDataType )myRedType,
- myRow * theRasterViewPort->drawableAreaXDim + myColumn );
- myGreenValue = readValue( myGdalGreenData, ( GDALDataType )myGreenType,
- myRow * theRasterViewPort->drawableAreaXDim + myColumn );
- myBlueValue = readValue( myGdalBlueData, ( GDALDataType )myBlueType,
- myRow * theRasterViewPort->drawableAreaXDim + myColumn );
+ myRedValue = readValue( redImageScanLine, ( GDALDataType )myRedType, i );
+ myGreenValue = readValue( greenImageScanLine, ( GDALDataType )myGreenType, i );
+ myBlueValue = readValue( blueImageScanLine, ( GDALDataType )myBlueType, i );
if ( mValidNoDataValue && (( fabs( myRedValue - mNoDataValue ) <= TINY_VALUE || myRedValue != myRedValue ) || ( fabs( myGreenValue - mNoDataValue ) <= TINY_VALUE || myGreenValue != myGreenValue ) || ( fabs( myBlueValue - mNoDataValue ) <= TINY_VALUE || myBlueValue != myBlueValue ) ) )
{
- myLineBuffer[ myColumn ] = myDefaultColor;
+ redImageScanLine[ i ] = myDefaultColor;
continue;
}
if ( !myRedContrastEnhancement->isValueInDisplayableRange( myRedValue ) || !myGreenContrastEnhancement->isValueInDisplayableRange( myGreenValue ) || !myBlueContrastEnhancement->isValueInDisplayableRange( myBlueValue ) )
{
- myLineBuffer[ myColumn ] = myDefaultColor;
+ redImageScanLine[ i ] = myDefaultColor;
continue;
}
myAlphaValue = mRasterTransparency.alphaValue( myRedValue, myGreenValue, myBlueValue, mTransparencyLevel );
if ( 0 == myAlphaValue )
{
- myLineBuffer[ myColumn ] = myDefaultColor;
+ redImageScanLine[ i ] = myDefaultColor;
continue;
}
@@ -4451,34 +4449,9 @@
myStretchedBlueValue = 255 - myStretchedBlueValue;
}
- myLineBuffer[ myColumn ] = qRgba( myStretchedRedValue, myStretchedGreenValue, myStretchedBlueValue, myAlphaValue );
+ redImageScanLine[ i ] = qRgba( myStretchedRedValue, myStretchedGreenValue, myStretchedBlueValue, myAlphaValue );
}
}
- //free the scanline memory
- CPLFree( myGdalRedData );
- CPLFree( myGdalGreenData );
- CPLFree( myGdalBlueData );
-
-#ifdef QGISDEBUG
- QPixmap *pm = dynamic_cast<QPixmap *>( theQPainter->device() );
- if ( pm )
- {
- QgsDebugMsg( "theQPainter stats: " );
- QgsDebugMsg( "width = " + QString::number( pm->width() ) );
- QgsDebugMsg( "height = " + QString::number( pm->height() ) );
- pm->save( "/tmp/qgis-rasterlayer-drawmultibandcolor-test-a.png", "PNG" );
- }
-#endif
-
- paintImageToCanvas( theQPainter, theRasterViewPort, theQgsMapToPixel, &myQImage );
-
-#ifdef QGISDEBUG
- QgsDebugMsg( "theQPainter->drawImage." );
- if ( pm )
- {
- pm->save( "/tmp/qgis-rasterlayer-drawmultibandcolor-test-b.png", "PNG" );
- }
-#endif
}
void QgsRasterLayer::drawMultiBandSingleBandGray( QPainter * theQPainter, QgsRasterViewPort * theRasterViewPort,
@@ -4518,69 +4491,58 @@
GDALRasterBandH myGdalBand = GDALGetRasterBand( mGdalDataset, theBandNo );
GDALDataType myDataType = GDALGetRasterDataType( myGdalBand );
- void *myGdalScanData = readData( myGdalBand, theRasterViewPort );
- /* Check for out of memory error */
- if ( myGdalScanData == NULL )
- {
- return;
- }
+ QgsRasterImageBuffer imageBuffer( myGdalBand, theQPainter, theRasterViewPort, theQgsMapToPixel, &mGeoTransform[0] );
+ imageBuffer.reset();
- QImage myQImage = QImage( theRasterViewPort->drawableAreaXDim, theRasterViewPort->drawableAreaYDim, QImage::Format_ARGB32 );
+ QRgb* imageScanLine = 0;
+ void* rasterScanLine = 0;
+
QRgb myDefaultColor = qRgba( 255, 255, 255, 0 );
-
double myPixelValue = 0.0;
int myRedValue = 0;
int myGreenValue = 0;
int myBlueValue = 0;
int myAlphaValue = 0;
- QgsDebugMsg( "Starting main render loop" );
- for ( int myRow = 0; myRow < theRasterViewPort->drawableAreaYDim; ++myRow )
+ while ( imageBuffer.nextScanLine( &imageScanLine, &rasterScanLine ) )
{
- QRgb* myLineBuffer = ( QRgb* )myQImage.scanLine( myRow );
- for ( int myColumn = 0; myColumn < theRasterViewPort->drawableAreaXDim; ++myColumn )
+ for ( int i = 0; i < theRasterViewPort->drawableAreaXDim; ++i )
{
- myRedValue = 0;
- myGreenValue = 0;
- myBlueValue = 0;
- myPixelValue = readValue( myGdalScanData, ( GDALDataType )myDataType,
- myRow * theRasterViewPort->drawableAreaXDim + myColumn );
+ myRedValue = 0; myGreenValue = 0; myBlueValue = 0;
+ myPixelValue = readValue( rasterScanLine, ( GDALDataType )myDataType, i );
if ( mValidNoDataValue && ( fabs( myPixelValue - mNoDataValue ) <= TINY_VALUE || myPixelValue != myPixelValue ) )
{
- myLineBuffer[ myColumn ] = myDefaultColor;
+ imageScanLine[ i ] = myDefaultColor;
continue;
}
myAlphaValue = mRasterTransparency.alphaValue( myPixelValue, mTransparencyLevel );
if ( 0 == myAlphaValue )
{
- myLineBuffer[ myColumn ] = myDefaultColor;
+ imageScanLine[ i ] = myDefaultColor;
continue;
}
if ( !mRasterShader->shade( myPixelValue, &myRedValue, &myGreenValue, &myBlueValue ) )
{
- myLineBuffer[ myColumn ] = myDefaultColor;
+ imageScanLine[ i ] = myDefaultColor;
continue;
}
if ( mInvertColor )
{
//Invert flag, flip blue and read
- myLineBuffer[ myColumn ] = qRgba( myBlueValue, myGreenValue, myRedValue, myAlphaValue );
+ imageScanLine[ i ] = qRgba( myBlueValue, myGreenValue, myRedValue, myAlphaValue );
}
else
{
//Normal
- myLineBuffer[ myColumn ] = qRgba( myRedValue, myGreenValue, myBlueValue, myAlphaValue );
+ imageScanLine[ i ] = qRgba( myRedValue, myGreenValue, myBlueValue, myAlphaValue );
}
}
}
- CPLFree( myGdalScanData );
-
- paintImageToCanvas( theQPainter, theRasterViewPort, theQgsMapToPixel, &myQImage );
}
/**
@@ -4606,51 +4568,45 @@
GDALRasterBandH myGdalBand = GDALGetRasterBand( mGdalDataset, theBandNo );
GDALDataType myDataType = GDALGetRasterDataType( myGdalBand );
- void *myGdalScanData = readData( myGdalBand, theRasterViewPort );
- /* Check for out of memory error */
- if ( myGdalScanData == NULL )
- {
- return;
- }
+ QgsRasterImageBuffer imageBuffer( myGdalBand, theQPainter, theRasterViewPort, theQgsMapToPixel, &mGeoTransform[0] );
+ imageBuffer.reset();
- QImage myQImage = QImage( theRasterViewPort->drawableAreaXDim, theRasterViewPort->drawableAreaYDim, QImage::Format_ARGB32 );
+ QRgb* imageScanLine = 0;
+ void* rasterScanLine = 0;
+
QRgb myDefaultColor = qRgba( 255, 255, 255, 0 );
-
double myPixelValue = 0.0;
int myRedValue = 0;
int myGreenValue = 0;
int myBlueValue = 0;
int myAlphaValue = 0;
- QgsDebugMsg( "Starting main render loop" );
- for ( int myRow = 0; myRow < theRasterViewPort->drawableAreaYDim; ++myRow )
+ while ( imageBuffer.nextScanLine( &imageScanLine, &rasterScanLine ) )
{
- QRgb* myLineBuffer = ( QRgb* )myQImage.scanLine( myRow );
- for ( int myColumn = 0; myColumn < theRasterViewPort->drawableAreaXDim; ++myColumn )
+ for ( int i = 0; i < theRasterViewPort->drawableAreaXDim; ++i )
{
myRedValue = 0;
myGreenValue = 0;
myBlueValue = 0;
- myPixelValue = readValue( myGdalScanData, ( GDALDataType )myDataType,
- myRow * theRasterViewPort->drawableAreaXDim + myColumn );
+ myPixelValue = readValue( rasterScanLine, ( GDALDataType )myDataType, i );
if ( mValidNoDataValue && ( fabs( myPixelValue - mNoDataValue ) <= TINY_VALUE || myPixelValue != myPixelValue ) )
{
- myLineBuffer[ myColumn ] = myDefaultColor;
+ imageScanLine[ i ] = myDefaultColor;
continue;
}
myAlphaValue = mRasterTransparency.alphaValue( myPixelValue, mTransparencyLevel );
if ( 0 == myAlphaValue )
{
- myLineBuffer[ myColumn ] = myDefaultColor;
+ imageScanLine[ i ] = myDefaultColor;
continue;
}
if ( !mRasterShader->shade( myPixelValue, &myRedValue, &myGreenValue, &myBlueValue ) )
{
- myLineBuffer[ myColumn ] = myDefaultColor;
+ imageScanLine[ i ] = myDefaultColor;
continue;
}
@@ -4658,19 +4614,16 @@
{
//Invert flag, flip blue and read
double myGrayValue = ( 0.3 * ( double )myRedValue ) + ( 0.59 * ( double )myGreenValue ) + ( 0.11 * ( double )myBlueValue );
- myLineBuffer[ myColumn ] = qRgba(( int )myGrayValue, ( int )myGrayValue, ( int )myGrayValue, myAlphaValue );
+ imageScanLine[ i ] = qRgba(( int )myGrayValue, ( int )myGrayValue, ( int )myGrayValue, myAlphaValue );
}
else
{
//Normal
double myGrayValue = ( 0.3 * ( double )myBlueValue ) + ( 0.59 * ( double )myGreenValue ) + ( 0.11 * ( double )myRedValue );
- myLineBuffer[ myColumn ] = qRgba(( int )myGrayValue, ( int )myGrayValue, ( int )myGrayValue, myAlphaValue );
+ imageScanLine[ i ] = qRgba(( int )myGrayValue, ( int )myGrayValue, ( int )myGrayValue, myAlphaValue );
}
}
}
- CPLFree( myGdalScanData );
-
- paintImageToCanvas( theQPainter, theRasterViewPort, theQgsMapToPixel, &myQImage );
}
/**
@@ -4694,22 +4647,14 @@
QgsRasterBandStats myRasterBandStats = bandStatistics( theBandNo );
GDALRasterBandH myGdalBand = GDALGetRasterBand( mGdalDataset, theBandNo );
GDALDataType myDataType = GDALGetRasterDataType( myGdalBand );
- void *myGdalScanData = readData( myGdalBand, theRasterViewPort );
- /* Check for out of memory error */
- if ( myGdalScanData == NULL )
- {
- return;
- }
+ QgsRasterImageBuffer imageBuffer( myGdalBand, theQPainter, theRasterViewPort, theQgsMapToPixel, &mGeoTransform[0] );
+ imageBuffer.reset();
- QImage myQImage = QImage( theRasterViewPort->drawableAreaXDim, theRasterViewPort->drawableAreaYDim, QImage::Format_ARGB32 );
+ QRgb* imageScanLine = 0;
+ void* rasterScanLine = 0;
+
QRgb myDefaultColor = qRgba( 255, 255, 255, 0 );
-
- if ( NULL == mRasterShader )
- {
- return;
- }
-
double myMinimumValue = 0.0;
double myMaximumValue = 0.0;
//Use standard deviations if set, otherwise, use min max of band
@@ -4733,52 +4678,46 @@
int myBlueValue = 0;
int myAlphaValue = 0;
- QgsDebugMsg( "Starting main render loop" );
- for ( int myRow = 0; myRow < theRasterViewPort->drawableAreaYDim; ++myRow )
+ while ( imageBuffer.nextScanLine( &imageScanLine, &rasterScanLine ) )
{
- QRgb* myLineBuffer = ( QRgb* )myQImage.scanLine( myRow );
- for ( int myColumn = 0; myColumn < theRasterViewPort->drawableAreaXDim; ++myColumn )
+ for ( int i = 0; i < theRasterViewPort->drawableAreaXDim; ++i )
{
myRedValue = 0;
myGreenValue = 0;
myBlueValue = 0;
- myPixelValue = readValue( myGdalScanData, ( GDALDataType )myDataType,
- myRow * theRasterViewPort->drawableAreaXDim + myColumn );
+ myPixelValue = readValue( rasterScanLine, ( GDALDataType )myDataType, i );
if ( mValidNoDataValue && ( fabs( myPixelValue - mNoDataValue ) <= TINY_VALUE || myPixelValue != myPixelValue ) )
{
- myLineBuffer[ myColumn ] = myDefaultColor;
+ imageScanLine[ i ] = myDefaultColor;
continue;
}
myAlphaValue = mRasterTransparency.alphaValue( myPixelValue, mTransparencyLevel );
if ( 0 == myAlphaValue )
{
- myLineBuffer[ myColumn ] = myDefaultColor;
+ imageScanLine[ i ] = myDefaultColor;
continue;
}
if ( !mRasterShader->shade( myPixelValue, &myRedValue, &myGreenValue, &myBlueValue ) )
{
- myLineBuffer[ myColumn ] = myDefaultColor;
+ imageScanLine[ i ] = myDefaultColor;
continue;
}
if ( mInvertColor )
{
//Invert flag, flip blue and read
- myLineBuffer[ myColumn ] = qRgba( myBlueValue, myGreenValue, myRedValue, myAlphaValue );
+ imageScanLine[ i ] = qRgba( myBlueValue, myGreenValue, myRedValue, myAlphaValue );
}
else
{
//Normal
- myLineBuffer[ myColumn ] = qRgba( myRedValue, myGreenValue, myBlueValue, myAlphaValue );
+ imageScanLine[ i ] = qRgba( myRedValue, myGreenValue, myBlueValue, myAlphaValue );
}
}
}
- CPLFree( myGdalScanData );
-
- paintImageToCanvas( theQPainter, theRasterViewPort, theQgsMapToPixel, &myQImage );
}
/**
@@ -4804,19 +4743,19 @@
GDALRasterBandH myGdalBand = GDALGetRasterBand( mGdalDataset, theBandNo );
GDALDataType myDataType = GDALGetRasterDataType( myGdalBand );
- void *myGdalScanData = readData( myGdalBand, theRasterViewPort );
+ QgsRasterImageBuffer imageBuffer( myGdalBand, theQPainter, theRasterViewPort, theQgsMapToPixel, &mGeoTransform[0] );
+ imageBuffer.reset();
- /* Check for out of memory error */
- if ( myGdalScanData == NULL )
- {
- return;
- }
+ QRgb* imageScanLine = 0;
+ void* rasterScanLine = 0;
- QImage myQImage = QImage( theRasterViewPort->drawableAreaXDim, theRasterViewPort->drawableAreaYDim, QImage::Format_ARGB32 );
QRgb myDefaultColor = qRgba( 255, 255, 255, 0 );
+ double myGrayValue = 0.0;
+ int myGrayVal = 0;
+ int myAlphaValue = 0;
+ QgsContrastEnhancement* myContrastEnhancement = contrastEnhancement( theBandNo );
QgsRasterBandStats myGrayBandStats;
-
if ( QgsContrastEnhancement::NoEnhancement != contrastEnhancementAlgorithm() && !mUserDefinedGrayMinimumMaximum && mStandardDeviations > 0 )
{
mGrayMinimumMaximumEstimated = false;
@@ -4836,41 +4775,28 @@
}
- QgsDebugMsg( "Starting main render loop" );
- // print each point in myGdalScanData with equal parts R, G, B or make it show as gray
- double myGrayValue = 0.0;
- int myGrayVal = 0;
- int myAlphaValue = 0;
- QgsContrastEnhancement* myContrastEnhancement = contrastEnhancement( theBandNo );
- for ( int myRow = 0; myRow < theRasterViewPort->drawableAreaYDim; ++myRow )
+ while ( imageBuffer.nextScanLine( &imageScanLine, &rasterScanLine ) )
{
- QRgb* myLineBuffer = ( QRgb* )myQImage.scanLine( myRow );
- for ( int myColumn = 0; myColumn < theRasterViewPort->drawableAreaXDim; ++myColumn )
+ for ( int i = 0; i < theRasterViewPort->drawableAreaXDim; ++i )
{
- myGrayValue = readValue( myGdalScanData, myDataType,
- myRow * theRasterViewPort->drawableAreaXDim + myColumn );
+ myGrayValue = readValue( rasterScanLine, ( GDALDataType )myDataType, i );
- // If mNoDataValue is 'nan', the comparison
- // against myGrayVal will always fail ( nan==nan always
- // returns false, by design), hence the slightly odd comparison
- // of myGrayVal against itself.
-
if ( mValidNoDataValue && ( fabs( myGrayValue - mNoDataValue ) <= TINY_VALUE || myGrayValue != myGrayValue ) )
{
- myLineBuffer[ myColumn ] = myDefaultColor;
+ imageScanLine[ i ] = myDefaultColor;
continue;
}
if ( !myContrastEnhancement->isValueInDisplayableRange( myGrayValue ) )
{
- myLineBuffer[ myColumn ] = myDefaultColor;
+ imageScanLine[ i ] = myDefaultColor;
continue;
}
myAlphaValue = mRasterTransparency.alphaValue( myGrayValue, mTransparencyLevel );
if ( 0 == myAlphaValue )
{
- myLineBuffer[ myColumn ] = myDefaultColor;
+ imageScanLine[ i ] = myDefaultColor;
continue;
}
@@ -4882,16 +4808,9 @@
myGrayVal = 255 - myGrayVal;
}
- myLineBuffer[ myColumn ] = qRgba( myGrayVal, myGrayVal, myGrayVal, myAlphaValue );
+ imageScanLine[ i ] = qRgba( myGrayVal, myGrayVal, myGrayVal, myAlphaValue );
}
}
-
- CPLFree( myGdalScanData );
-
- QgsDebugMsg( "Render done, preparing to copy to canvas" );
-
- paintImageToCanvas( theQPainter, theRasterViewPort, theQgsMapToPixel, &myQImage );
-
} // QgsRasterLayer::drawSingleBandGray
void QgsRasterLayer::drawSingleBandPseudoColor( QPainter * theQPainter,
@@ -4909,17 +4828,14 @@
QgsRasterBandStats myRasterBandStats = bandStatistics( theBandNo );
GDALRasterBandH myGdalBand = GDALGetRasterBand( mGdalDataset, theBandNo );
GDALDataType myDataType = GDALGetRasterDataType( myGdalBand );
- void *myGdalScanData = readData( myGdalBand, theRasterViewPort );
- /* Check for out of memory error */
- if ( myGdalScanData == NULL )
- {
- return;
- }
+ QgsRasterImageBuffer imageBuffer( myGdalBand, theQPainter, theRasterViewPort, theQgsMapToPixel, &mGeoTransform[0] );
+ imageBuffer.reset();
- QImage myQImage = QImage( theRasterViewPort->drawableAreaXDim, theRasterViewPort->drawableAreaYDim, QImage::Format_ARGB32 );
+ QRgb* imageScanLine = 0;
+ void* rasterScanLine = 0;
+
QRgb myDefaultColor = qRgba( 255, 255, 255, 0 );
-
if ( NULL == mRasterShader )
{
return;
@@ -4942,57 +4858,50 @@
mRasterShader->setMinimumValue( myMinimumValue );
mRasterShader->setMaximumValue( myMaximumValue );
-
int myRedValue = 255;
int myGreenValue = 255;
int myBlueValue = 255;
double myPixelValue = 0.0;
int myAlphaValue = 0;
- QgsDebugMsg( "Starting main render loop" );
- for ( int myRow = 0; myRow < theRasterViewPort->drawableAreaYDim; ++myRow )
+
+ while ( imageBuffer.nextScanLine( &imageScanLine, &rasterScanLine ) )
{
- QRgb* myLineBuffer = ( QRgb* )myQImage.scanLine( myRow );
- for ( int myColumn = 0; myColumn < theRasterViewPort->drawableAreaXDim; ++myColumn )
+ for ( int i = 0; i < theRasterViewPort->drawableAreaXDim; ++i )
{
- myPixelValue = readValue( myGdalScanData, myDataType,
- myRow * theRasterViewPort->drawableAreaXDim + myColumn );
+ myPixelValue = readValue( rasterScanLine, myDataType, i );
if ( mValidNoDataValue && ( fabs( myPixelValue - mNoDataValue ) <= TINY_VALUE || myPixelValue != myPixelValue ) )
{
- myLineBuffer[ myColumn ] = myDefaultColor;
+ imageScanLine[ i ] = myDefaultColor;
continue;
}
myAlphaValue = mRasterTransparency.alphaValue( myPixelValue, mTransparencyLevel );
if ( 0 == myAlphaValue )
{
- myLineBuffer[ myColumn ] = myDefaultColor;
+ imageScanLine[ i ] = myDefaultColor;
continue;
}
if ( !mRasterShader->shade( myPixelValue, &myRedValue, &myGreenValue, &myBlueValue ) )
{
- myLineBuffer[ myColumn ] = myDefaultColor;
+ imageScanLine[ i ] = myDefaultColor;
continue;
}
if ( mInvertColor )
{
//Invert flag, flip blue and read
- myLineBuffer[ myColumn ] = qRgba( myBlueValue, myGreenValue, myRedValue, myAlphaValue );
+ imageScanLine[ i ] = qRgba( myBlueValue, myGreenValue, myRedValue, myAlphaValue );
}
else
{
//Normal
- myLineBuffer[ myColumn ] = qRgba( myRedValue, myGreenValue, myBlueValue, myAlphaValue );
+ imageScanLine[ i ] = qRgba( myRedValue, myGreenValue, myBlueValue, myAlphaValue );
}
- } //end of columnwise loop
- } //end of rowwise loop
-
- CPLFree( myGdalScanData );
-
- paintImageToCanvas( theQPainter, theRasterViewPort, theQgsMapToPixel, &myQImage );
+ }
+ }
}
@@ -5085,7 +4994,7 @@
//Catch special rendering cases
//INSTANCE: 1x1
- if( 1 == theRasterViewPort->clippedWidth && 1 == theRasterViewPort->clippedHeight )
+ if ( 1 == theRasterViewPort->clippedWidth && 1 == theRasterViewPort->clippedHeight )
{
QColor myColor( theImage->pixel( 0, 0 ) );
myColor.setAlpha( qAlpha( theImage->pixel( 0, 0 ) ) );
@@ -5096,17 +5005,19 @@
QBrush( myColor ) );
}
//1x2, 2x1 or 2x2
- else if( 2 >= theRasterViewPort->clippedWidth && 2 >= theRasterViewPort->clippedHeight )
+ else if ( 2 >= theRasterViewPort->clippedWidth && 2 >= theRasterViewPort->clippedHeight )
{
int myPixelBoundaryX = 0;
int myPixelBoundaryY = 0;
- if( theQgsMapToPixel ) {
- myPixelBoundaryX = static_cast<int>( theRasterViewPort->topLeftPoint.x() + 0.5 ) + static_cast<int>( fabs ( mGeoTransform[1] / theQgsMapToPixel->mapUnitsPerPixel() ) ) - paintXoffset;
- myPixelBoundaryY = static_cast<int>( theRasterViewPort->topLeftPoint.y() + 0.5 ) + static_cast<int>( fabs(mGeoTransform[5] / theQgsMapToPixel->mapUnitsPerPixel() )) - paintYoffset;
+ if ( theQgsMapToPixel )
+ {
+ myPixelBoundaryX = static_cast<int>( theRasterViewPort->topLeftPoint.x() + 0.5 ) + static_cast<int>( fabs( mGeoTransform[1] / theQgsMapToPixel->mapUnitsPerPixel() ) ) - paintXoffset;
+ myPixelBoundaryY = static_cast<int>( theRasterViewPort->topLeftPoint.y() + 0.5 ) + static_cast<int>( fabs( mGeoTransform[5] / theQgsMapToPixel->mapUnitsPerPixel() ) ) - paintYoffset;
}
//INSTANCE: 1x2
- if( 1 == theRasterViewPort->clippedWidth ) {
+ if ( 1 == theRasterViewPort->clippedWidth )
+ {
QColor myColor( theImage->pixel( 0, 0 ) );
myColor.setAlpha( qAlpha( theImage->pixel( 0, 0 ) ) );
theQPainter->fillRect( static_cast<int>( theRasterViewPort->topLeftPoint.x() + 0.5 ),
@@ -5114,7 +5025,7 @@
static_cast<int>( theRasterViewPort->bottomRightPoint.x() ),
static_cast<int>( myPixelBoundaryY ),
QBrush( myColor ) );
- myColor = QColor( theImage->pixel( 0, 1) );
+ myColor = QColor( theImage->pixel( 0, 1 ) );
myColor.setAlpha( qAlpha( theImage->pixel( 0, 1 ) ) );
theQPainter->fillRect( static_cast<int>( theRasterViewPort->topLeftPoint.x() + 0.5 ),
static_cast<int>( myPixelBoundaryY ),
@@ -5122,12 +5033,13 @@
static_cast<int>( theRasterViewPort->bottomRightPoint.y() ),
QBrush( myColor ) );
}
- else {
+ else
+ {
//INSTANCE: 2x1
- if( 1 == theRasterViewPort->clippedHeight )
+ if ( 1 == theRasterViewPort->clippedHeight )
{
QColor myColor( theImage->pixel( 0, 0 ) );
- myColor.setAlpha( qAlpha( theImage->pixel( 0,0 ) ) );
+ myColor.setAlpha( qAlpha( theImage->pixel( 0, 0 ) ) );
theQPainter->fillRect( static_cast<int>( theRasterViewPort->topLeftPoint.x() + 0.5 ),
static_cast<int>( theRasterViewPort->topLeftPoint.y() + 0.5 ),
static_cast<int>( myPixelBoundaryX ),
@@ -5148,10 +5060,10 @@
myColor.setAlpha( qAlpha( theImage->pixel( 0, 0 ) ) );
theQPainter->fillRect( static_cast<int>( theRasterViewPort->topLeftPoint.x() + 0.5 ),
static_cast<int>( theRasterViewPort->topLeftPoint.y() + 0.5 ),
- static_cast<int>(myPixelBoundaryX ),
+ static_cast<int>( myPixelBoundaryX ),
static_cast<int>( myPixelBoundaryY ),
QBrush( myColor ) );
- myColor = QColor( theImage->pixel( 1, 0 ) );
+ myColor = QColor( theImage->pixel( 1, 0 ) );
myColor.setAlpha( qAlpha( theImage->pixel( 1, 0 ) ) );
theQPainter->fillRect( static_cast<int>( myPixelBoundaryX ),
static_cast<int>( theRasterViewPort->topLeftPoint.y() + 0.5 ),
@@ -5177,7 +5089,8 @@
}
// INSTANCE: > 2x2, so just use the image filled by GDAL
- else {
+ else
+ {
theQPainter->drawImage( static_cast<int>( theRasterViewPort->topLeftPoint.x() + 0.5 ),
static_cast<int>( theRasterViewPort->topLeftPoint.y() + 0.5 ),
*theImage,
@@ -5617,3 +5530,297 @@
QgsDebugMsg( "All checks failed, returning '" + QSTRING_NOT_SET + "'" );
return TRSTRING_NOT_SET;
}
+
+QgsRasterImageBuffer::QgsRasterImageBuffer( GDALRasterBandH rasterBand, QPainter* p, QgsRasterViewPort* viewPort, const QgsMapToPixel* mapToPixel, double* geoTransform ): \
+ mRasterBand( rasterBand ), mPainter( p ), mViewPort( viewPort ), mMapToPixel( mapToPixel ), mValid( false ), mWritingEnabled( true ), mDrawPixelRect( false ), mCurrentImage( 0 ), mCurrentGDALData( 0 ), mGeoTransform( geoTransform )
+{
+
+}
+
+QgsRasterImageBuffer::~QgsRasterImageBuffer()
+{
+ delete mCurrentImage;
+ CPLFree( mCurrentGDALData );
+}
+
+void QgsRasterImageBuffer::reset( int maxPixelsInVirtualMemory )
+{
+ if ( mRasterBand && mPainter && mViewPort && mMapToPixel )
+ {
+ mValid = true;
+ }
+ else
+ {
+ mValid = false;
+ return;
+ }
+
+ //decide on the partition of the image
+
+ int pixels = mViewPort->drawableAreaXDim * mViewPort->drawableAreaYDim;
+ int mNumPartImages = pixels / maxPixelsInVirtualMemory + 1.0;
+ mNumRasterRowsPerPart = ( double )mViewPort->clippedHeight / ( double )mNumPartImages + 0.5;
+
+ mCurrentPartRasterMin = -1;
+ mCurrentPartRasterMax = -1;
+ mCurrentPartImageRow = 0;
+ mNumCurrentImageRows = 0;
+
+ createNextPartImage();
+
+ if ( 2 >= mViewPort->clippedWidth && 2 >= mViewPort->clippedHeight )
+ {
+ //use Peter's fix for zoomed in rasters
+ mDrawPixelRect = true;
+ }
+}
+
+bool QgsRasterImageBuffer::nextScanLine( QRgb** imageScanLine, void** rasterScanLine )
+{
+ if ( !mValid )
+ {
+ return false;
+ }
+
+ if ( !mCurrentGDALData || ! mCurrentImage )
+ {
+ return false;
+ }
+
+ if ( mCurrentPartImageRow >= ( mNumCurrentImageRows ) )
+ {
+ if ( !createNextPartImage() )
+ {
+ return false;
+ }
+ }
+
+ if ( mWritingEnabled )
+ {
+ *imageScanLine = ( QRgb* )( mCurrentImage->scanLine( mCurrentPartImageRow ) );
+ }
+ else
+ {
+ *imageScanLine = 0;
+ }
+ GDALDataType type = GDALGetRasterDataType( mRasterBand );
+ int size = GDALGetDataTypeSize( type ) / 8;
+ *rasterScanLine = mCurrentGDALData + mCurrentPartImageRow * mViewPort->drawableAreaXDim * size;
+
+ ++mCurrentPartImageRow;
+ ++mCurrentRow;
+ return true;
+}
+
+bool QgsRasterImageBuffer::createNextPartImage()
+{
+ //draw the last image if mCurrentImage if it exists
+ if ( mCurrentImage )
+ {
+ if ( mWritingEnabled )
+ {
+ if ( 2 >= mViewPort->clippedWidth && 2 >= mViewPort->clippedHeight )
+ {
+ drawPixelRectangle();
+ }
+ else
+ {
+ double xLeft = mViewPort->topLeftPoint.x();
+ double yTop = mViewPort->topLeftPoint.y() + fabs( mGeoTransform[5] ) * mCurrentPartRasterMin / mMapToPixel->mapUnitsPerPixel();
+ mPainter->drawImage( QPointF( xLeft, yTop + 0.5 ), *mCurrentImage );
+ }
+ }
+ }
+
+ delete mCurrentImage; mCurrentImage = 0;
+ CPLFree( mCurrentGDALData ); mCurrentGDALData = 0;
+
+ if ( mCurrentPartRasterMax >= mViewPort->clippedHeight )
+ {
+ return false; //already at the end...
+ }
+
+ mCurrentPartRasterMin = mCurrentPartRasterMax + 1;
+ mCurrentPartRasterMax = mCurrentPartRasterMin + mNumRasterRowsPerPart;
+ if ( mCurrentPartRasterMax > mViewPort->clippedHeight )
+ {
+ mCurrentPartRasterMax = mViewPort->clippedHeight;
+ }
+ mCurrentRow = mCurrentPartRasterMin;
+ mCurrentPartImageRow = 0;
+
+ //read GDAL image data
+ GDALDataType type = GDALGetRasterDataType( mRasterBand );
+ int size = GDALGetDataTypeSize( type ) / 8;
+ int xSize = mViewPort->drawableAreaXDim;
+
+ //make the raster tiles overlap at least 2 pixels to avoid white stripes
+ int overlapRows = 0;
+ overlapRows = mMapToPixel->mapUnitsPerPixel() / fabs( mGeoTransform[5] ) + 2;
+ if ( mCurrentPartRasterMax + overlapRows >= mViewPort->clippedHeight )
+ {
+ overlapRows = 0;
+ }
+ int rasterYSize = mCurrentPartRasterMax - mCurrentPartRasterMin + overlapRows;
+
+ int ySize = 0;
+ if ( 2 >= mViewPort->clippedWidth && 2 >= mViewPort->clippedHeight ) //for zoomed in rasters
+ {
+ rasterYSize = mViewPort->clippedHeight;
+ ySize = mViewPort->drawableAreaYDim;
+ }
+ else //normal mode
+ {
+ ySize = fabs((( rasterYSize ) / mMapToPixel->mapUnitsPerPixel() * mGeoTransform[5] ) ) + 0.5;
+ }
+ if ( ySize == 0 )
+ {
+ return false;
+ }
+ mNumCurrentImageRows = ySize;
+ mCurrentGDALData = VSIMalloc( size * xSize * ySize );
+ CPLErr myErr = GDALRasterIO( mRasterBand, GF_Read, mViewPort->rectXOffset, \
+ mViewPort->rectYOffset + mCurrentRow, mViewPort->clippedWidth, rasterYSize, \
+ mCurrentGDALData, xSize, ySize, type, 0, 0 );
+
+ if ( myErr != CPLE_None )
+ {
+ CPLFree( mCurrentGDALData );
+ mCurrentGDALData = 0;
+ return false;
+ }
+
+ //create the QImage
+ if ( mWritingEnabled )
+ {
+ mCurrentImage = new QImage( xSize, ySize, QImage::Format_ARGB32 );
+ mCurrentImage->fill( qRgba( 255, 255, 255, 0 ) );
+ }
+ else
+ {
+ mCurrentImage = 0;
+ }
+ return true;
+}
+
+void QgsRasterImageBuffer::drawPixelRectangle()
+{
+ // Set up the initial offset into the myQImage we want to copy to the map canvas
+ // This is useful when the source image pixels are larger than the screen image.
+ int paintXoffset = 0;
+ int paintYoffset = 0;
+
+ if ( mMapToPixel )
+ {
+ paintXoffset = static_cast<int>(
+ ( mViewPort->rectXOffsetFloat -
+ mViewPort->rectXOffset )
+ / mMapToPixel->mapUnitsPerPixel()
+ * fabs( mGeoTransform[1] )
+ );
+
+ paintYoffset = static_cast<int>(
+ ( mViewPort->rectYOffsetFloat -
+ mViewPort->rectYOffset )
+ / mMapToPixel->mapUnitsPerPixel()
+ * fabs( mGeoTransform[5] )
+ );
+ }
+
+ //fix for zoomed in rasters
+ //Catch special rendering cases
+ //INSTANCE: 1x1
+ if ( 1 == mViewPort->clippedWidth && 1 == mViewPort->clippedHeight )
+ {
+ QColor myColor( mCurrentImage->pixel( 0, 0 ) );
+ myColor.setAlpha( qAlpha( mCurrentImage->pixel( 0, 0 ) ) );
+ mPainter->fillRect( static_cast<int>( mViewPort->topLeftPoint.x() + 0.5 ),
+ static_cast<int>( mViewPort->topLeftPoint.y() + 0.5 ),
+ static_cast<int>( mViewPort->bottomRightPoint.x() ),
+ static_cast<int>( mViewPort->bottomRightPoint.y() ),
+ QBrush( myColor ) );
+ }
+ //1x2, 2x1 or 2x2
+ else if ( 2 >= mViewPort->clippedWidth && 2 >= mViewPort->clippedHeight )
+ {
+ int myPixelBoundaryX = 0;
+ int myPixelBoundaryY = 0;
+ if ( mMapToPixel )
+ {
+ myPixelBoundaryX = static_cast<int>( mViewPort->topLeftPoint.x() + 0.5 ) + static_cast<int>( fabs( mGeoTransform[1] / mMapToPixel->mapUnitsPerPixel() ) ) - paintXoffset;
+ myPixelBoundaryY = static_cast<int>( mViewPort->topLeftPoint.y() + 0.5 ) + static_cast<int>( fabs( mGeoTransform[5] / mMapToPixel->mapUnitsPerPixel() ) ) - paintYoffset;
+ }
+
+ //INSTANCE: 1x2
+ if ( 1 == mViewPort->clippedWidth )
+ {
+ QColor myColor( mCurrentImage->pixel( 0, 0 ) );
+ myColor.setAlpha( qAlpha( mCurrentImage->pixel( 0, 0 ) ) );
+ mPainter->fillRect( static_cast<int>( mViewPort->topLeftPoint.x() + 0.5 ),
+ static_cast<int>( mViewPort->topLeftPoint.y() + 0.5 ),
+ static_cast<int>( mViewPort->bottomRightPoint.x() ),
+ static_cast<int>( myPixelBoundaryY ),
+ QBrush( myColor ) );
+ myColor = QColor( mCurrentImage->pixel( 0, 1 ) );
+ myColor.setAlpha( qAlpha( mCurrentImage->pixel( 0, 1 ) ) );
+ mPainter->fillRect( static_cast<int>( mViewPort->topLeftPoint.x() + 0.5 ),
+ static_cast<int>( myPixelBoundaryY ),
+ static_cast<int>( mViewPort->bottomRightPoint.x() ),
+ static_cast<int>( mViewPort->bottomRightPoint.y() ),
+ QBrush( myColor ) );
+ }
+ else
+ {
+ //INSTANCE: 2x1
+ if ( 1 == mViewPort->clippedHeight )
+ {
+ QColor myColor( mCurrentImage->pixel( 0, 0 ) );
+ myColor.setAlpha( qAlpha( mCurrentImage->pixel( 0, 0 ) ) );
+ mPainter->fillRect( static_cast<int>( mViewPort->topLeftPoint.x() + 0.5 ),
+ static_cast<int>( mViewPort->topLeftPoint.y() + 0.5 ),
+ static_cast<int>( myPixelBoundaryX ),
+ static_cast<int>( mViewPort->bottomRightPoint.y() ),
+ QBrush( myColor ) );
+ myColor = QColor( mCurrentImage->pixel( 1, 0 ) );
+ myColor.setAlpha( qAlpha( mCurrentImage->pixel( 1, 0 ) ) );
+ mPainter->fillRect( static_cast<int>( myPixelBoundaryX ),
+ static_cast<int>( mViewPort->topLeftPoint.y() + 0.5 ),
+ static_cast<int>( mViewPort->bottomRightPoint.x() ),
+ static_cast<int>( mViewPort->bottomRightPoint.y() ),
+ QBrush( myColor ) );
+ }
+ //INSTANCE: 2x2
+ else
+ {
+ QColor myColor( mCurrentImage->pixel( 0, 0 ) );
+ myColor.setAlpha( qAlpha( mCurrentImage->pixel( 0, 0 ) ) );
+ mPainter->fillRect( static_cast<int>( mViewPort->topLeftPoint.x() + 0.5 ),
+ static_cast<int>( mViewPort->topLeftPoint.y() + 0.5 ),
+ static_cast<int>( myPixelBoundaryX ),
+ static_cast<int>( myPixelBoundaryY ),
+ QBrush( myColor ) );
+ myColor = QColor( mCurrentImage->pixel( 1, 0 ) );
+ myColor.setAlpha( qAlpha( mCurrentImage->pixel( 1, 0 ) ) );
+ mPainter->fillRect( static_cast<int>( myPixelBoundaryX ),
+ static_cast<int>( mViewPort->topLeftPoint.y() + 0.5 ),
+ static_cast<int>( mViewPort->bottomRightPoint.x() ),
+ static_cast<int>( myPixelBoundaryY ),
+ QBrush( myColor ) );
+ myColor = QColor( mCurrentImage->pixel( 0, 1 ) );
+ myColor.setAlpha( qAlpha( mCurrentImage->pixel( 0, 1 ) ) );
+ mPainter->fillRect( static_cast<int>( mViewPort->topLeftPoint.x() + 0.5 ),
+ static_cast<int>( myPixelBoundaryY ),
+ static_cast<int>( myPixelBoundaryX ),
+ static_cast<int>( mViewPort->bottomRightPoint.y() ),
+ QBrush( myColor ) );
+ myColor = QColor( mCurrentImage->pixel( 1, 1 ) );
+ myColor.setAlpha( qAlpha( mCurrentImage->pixel( 1, 1 ) ) );
+ mPainter->fillRect( static_cast<int>( myPixelBoundaryX ),
+ static_cast<int>( myPixelBoundaryY ),
+ static_cast<int>( mViewPort->bottomRightPoint.x() ),
+ static_cast<int>( mViewPort->bottomRightPoint.y() ),
+ QBrush( myColor ) );
+ }
+ }
+ }
+}
Modified: trunk/qgis/src/core/raster/qgsrasterlayer.h
===================================================================
--- trunk/qgis/src/core/raster/qgsrasterlayer.h 2010-01-20 22:40:19 UTC (rev 12808)
+++ trunk/qgis/src/core/raster/qgsrasterlayer.h 2010-01-21 09:23:15 UTC (rev 12809)
@@ -881,4 +881,59 @@
bool mValidNoDataValue;
};
+/*#include <QColor>
+
+typedef void* GDALRasterBandH;
+class QgsMapToPixel;
+struct QgsRasterViewPort;
+class QImage;
+class QPainter;*/
+
+/**A class encapsulates reading from a raster band and drawing the pixels to a painter.
+ The class allows sequential reading of the scan lines and setting the image scan line pixels. It automatically decides
+ on how much of the band / image should stay in virtual memory at a time*/
+class CORE_EXPORT QgsRasterImageBuffer
+{
+ public:
+ QgsRasterImageBuffer( GDALRasterBandH rasterBand, QPainter* p, \
+ QgsRasterViewPort* viewPort, const QgsMapToPixel* mapToPixel, double* mGeoTransform );
+ ~QgsRasterImageBuffer();
+ void reset( int maxPixelsInVirtualMemory = 5000000 );
+ /**Returns a pointer to the next scan line (or 0 if end)*/
+ bool nextScanLine( QRgb** imageScanLine, void** rasterScanLine );
+
+ void setWritingEnabled( bool enabled ) { mWritingEnabled = enabled; }
+
+ private:
+ QgsRasterImageBuffer(); //forbidden
+ /**Creates next part image. Returns false if at end*/
+ bool createNextPartImage();
+
+ /**Peter's fix for zoomed in rasters*/
+ void drawPixelRectangle();
+
+ GDALRasterBandH mRasterBand; //raster band
+ QPainter* mPainter;
+ QgsRasterViewPort* mViewPort;
+ const QgsMapToPixel* mMapToPixel;
+ double* mGeoTransform;
+
+ bool mValid;
+ /**True (default), if values are written to an image. If false, the class only reads the values, but does not create an image*/
+ bool mWritingEnabled;
+ /**Draws the raster pixels as rectangles. This is only used if the map units per pixel is very, very small*/
+ bool mDrawPixelRect;
+ int mCurrentRow;
+ int mNumPartImages; //number of part images
+ int mNumRasterRowsPerPart; //number of (raster source) rows per part
+ int mCurrentPartRasterMin; //minimum (raster source) row of current image
+ int mCurrentPartRasterMax; //maximum (raster source) row of current image
+ int mCurrentPartImageRow; //current image row
+ int mNumCurrentImageRows; //number of image rows for the current part
+
+ //current memory image and gdal scan data
+ QImage* mCurrentImage;
+ void* mCurrentGDALData;
+};
+
#endif
More information about the QGIS-commit
mailing list