@@ -248,6 +248,7 @@ QgsRasterLayer::~QgsRasterLayer()
248
248
GDALClose ( mGdalDataset );
249
249
}
250
250
}
251
+ delete mRasterShader ;
251
252
}
252
253
253
254
@@ -1536,7 +1537,7 @@ bool QgsRasterLayer::draw( QgsRenderContext& rendererContext )
1536
1537
// the drawable area can start to get very very large when you get down displaying 2x2 or smaller, this is becasue
1537
1538
// theQgsMapToPixel.mapUnitsPerPixel() is less then 1,
1538
1539
// so we will just get the pixel data and then render these special cases differently in paintImageToCanvas()
1539
- if ( 2 >= myRasterViewPort->clippedWidth && 2 >= myRasterViewPort->clippedHeight )
1540
+ if ( 2 >= myRasterViewPort->clippedWidth && 2 >= myRasterViewPort->clippedHeight )
1540
1541
{
1541
1542
myRasterViewPort->drawableAreaXDim = myRasterViewPort->clippedWidth ;
1542
1543
myRasterViewPort->drawableAreaYDim = myRasterViewPort->clippedHeight ;
@@ -1591,90 +1592,88 @@ bool QgsRasterLayer::draw( QgsRenderContext& rendererContext )
1591
1592
1592
1593
mDataProvider ->setDpi ( rendererContext.rasterScaleFactor () * 25.4 * rendererContext.scaleFactor () );
1593
1594
1594
- QImage* image =
1595
- mDataProvider -> draw (
1596
- myRasterExtent,
1597
- // Below should calculate to the actual pixel size of the
1598
- // part of the layer that's visible.
1599
- static_cast < int >( fabs (( myRasterViewPort-> clippedXMax - myRasterViewPort-> clippedXMin )
1600
- / theQgsMapToPixel. mapUnitsPerPixel () * mGeoTransform [ 1 ] ) + 1 ),
1601
- static_cast < int >( fabs (( myRasterViewPort-> clippedYMax - myRasterViewPort-> clippedYMin )
1602
- / theQgsMapToPixel. mapUnitsPerPixel () * mGeoTransform [ 5 ] ) + 1 )
1603
- // myRasterViewPort->drawableAreaXDim,
1604
- // myRasterViewPort->drawableAreaYDim
1605
- );
1606
-
1607
- if ( !image )
1595
+ // fetch image in several parts if it is too memory consuming
1596
+ // also some WMS servers have a pixel limit, so it's better to make several requests
1597
+ int totalPixelWidth = fabs (( myRasterViewPort-> clippedXMax - myRasterViewPort-> clippedXMin )
1598
+ / theQgsMapToPixel. mapUnitsPerPixel () * mGeoTransform [ 1 ] ) + 1 ;
1599
+ int totalPixelHeight = fabs (( myRasterViewPort-> clippedYMax - myRasterViewPort-> clippedYMin )
1600
+ / theQgsMapToPixel. mapUnitsPerPixel () * mGeoTransform [ 5 ] ) + 1 ;
1601
+ int numParts = totalPixelWidth * totalPixelHeight / 5000000 + 1.0 ;
1602
+ int numRowsPerPart = totalPixelHeight / numParts + 1.0 ;
1603
+
1604
+
1605
+ int currentPixelOffsetY = 0 ; // top y-coordinate of current raster part
1606
+ // the width of a WMS image part
1607
+ int pixelWidth = ( myRasterExtent. xMaximum () - myRasterExtent. xMinimum () ) / theQgsMapToPixel. mapUnitsPerPixel ();
1608
+ for ( int i = 0 ; i < numParts; ++i )
1608
1609
{
1609
- // An error occurred.
1610
- mErrorCaption = mDataProvider -> lastErrorTitle ();
1611
- mError = mDataProvider -> lastError ( );
1610
+ // fetch a small overlap of 2 pixels between two adjacent tiles to avoid white stripes
1611
+ QgsRectangle rasterPartRect ( myRasterExtent. xMinimum (), myRasterExtent. yMaximum () - ( currentPixelOffsetY + numRowsPerPart + 2 ) * theQgsMapToPixel. mapUnitsPerPixel (), \
1612
+ myRasterExtent. xMaximum (), myRasterExtent. yMaximum () - currentPixelOffsetY * theQgsMapToPixel. mapUnitsPerPixel () );
1612
1613
1613
- delete myRasterViewPort;
1614
- return FALSE ;
1615
- }
1614
+ int pixelHeight = rasterPartRect.height () / theQgsMapToPixel.mapUnitsPerPixel ();
1615
+ QImage* image = mDataProvider ->draw ( rasterPartRect, pixelWidth, pixelHeight );
1616
+
1617
+ if ( !image )
1618
+ {
1619
+ // An error occurred.
1620
+ mErrorCaption = mDataProvider ->lastErrorTitle ();
1621
+ mError = mDataProvider ->lastError ();
1622
+
1623
+ delete myRasterViewPort;
1624
+ return FALSE ;
1625
+ }
1616
1626
1617
- QgsDebugMsg ( " Done mDataProvider->draw." );
1618
- QgsDebugMsg ( " image stats: " );
1627
+ QgsDebugMsg ( " Done mDataProvider->draw." );
1628
+ QgsDebugMsg ( " image stats: " );
1619
1629
1620
- QgsDebugMsg ( QString ( " depth=%1" ).arg ( image->depth () ) );
1621
- QgsDebugMsg ( QString ( " bytes=%1" ).arg ( image->numBytes () ) );
1622
- QgsDebugMsg ( QString ( " width=%1" ).arg ( image->width () ) );
1623
- QgsDebugMsg ( QString ( " height=%1" ).arg ( image->height () ) );
1630
+ QgsDebugMsg ( QString ( " depth=%1" ).arg ( image->depth () ) );
1631
+ QgsDebugMsg ( QString ( " bytes=%1" ).arg ( image->numBytes () ) );
1632
+ QgsDebugMsg ( QString ( " width=%1" ).arg ( image->width () ) );
1633
+ QgsDebugMsg ( QString ( " height=%1" ).arg ( image->height () ) );
1624
1634
1625
- QgsDebugMsg ( " Want to theQPainter->drawImage with" );
1635
+ QgsDebugMsg ( " Want to theQPainter->drawImage with" );
1626
1636
1627
- QgsDebugMsg ( QString ( " origin x: %1" ).arg ( myRasterViewPort->topLeftPoint .x () ) );
1628
- QgsDebugMsg ( QString ( " (int)origin x: %1" ).arg ( static_cast <int >( myRasterViewPort->topLeftPoint .x () ) ) );
1629
- QgsDebugMsg ( QString ( " origin y: %1" ).arg ( myRasterViewPort->topLeftPoint .y () ) );
1630
- QgsDebugMsg ( QString ( " (int)origin y: %1" ).arg ( static_cast <int >( myRasterViewPort->topLeftPoint .y () ) ) );
1637
+ QgsDebugMsg ( QString ( " origin x: %1" ).arg ( myRasterViewPort->topLeftPoint .x () ) );
1638
+ QgsDebugMsg ( QString ( " (int)origin x: %1" ).arg ( static_cast <int >( myRasterViewPort->topLeftPoint .x () ) ) );
1639
+ QgsDebugMsg ( QString ( " origin y: %1" ).arg ( myRasterViewPort->topLeftPoint .y () ) );
1640
+ QgsDebugMsg ( QString ( " (int)origin y: %1" ).arg ( static_cast <int >( myRasterViewPort->topLeftPoint .y () ) ) );
1631
1641
1632
- // Set the transparency for the whole layer
1633
- // QImage::setAlphaChannel does not work quite as expected so set each pixel individually
1634
- // Currently this is only done for WMS images, which should be small enough not to impact performance
1642
+ // Set the transparency for the whole layer
1643
+ // QImage::setAlphaChannel does not work quite as expected so set each pixel individually
1644
+ // Currently this is only done for WMS images, which should be small enough not to impact performance
1635
1645
1636
- if ( mTransparencyLevel != 255 ) // improve performance if layer transparency not altered
1637
- {
1638
- QImage* transparentImageCopy = new QImage ( *image ); // copy image if there is user transparency
1639
- image = transparentImageCopy;
1640
- int myWidth = image->width ();
1641
- int myHeight = image->height ();
1642
- QRgb myRgb;
1643
- int newTransparency;
1644
- for ( int myHeightRunner = 0 ; myHeightRunner < myHeight; myHeightRunner++ )
1646
+ if ( mTransparencyLevel != 255 ) // improve performance if layer transparency not altered
1645
1647
{
1646
- QRgb* myLineBuffer = ( QRgb* ) transparentImageCopy->scanLine ( myHeightRunner );
1647
- for ( int myWidthRunner = 0 ; myWidthRunner < myWidth; myWidthRunner++ )
1648
+ QImage* transparentImageCopy = new QImage ( *image ); // copy image if there is user transparency
1649
+ image = transparentImageCopy;
1650
+ int myWidth = image->width ();
1651
+ int myHeight = image->height ();
1652
+ QRgb myRgb;
1653
+ int newTransparency;
1654
+ for ( int myHeightRunner = 0 ; myHeightRunner < myHeight; myHeightRunner++ )
1648
1655
{
1649
- myRgb = image->pixel ( myWidthRunner, myHeightRunner );
1650
- // combine transparency from WMS and layer transparency
1651
- newTransparency = ( double ) mTransparencyLevel / 255.0 * ( double )( qAlpha ( myRgb ) );
1652
- myLineBuffer[ myWidthRunner ] = qRgba ( qRed ( myRgb ), qGreen ( myRgb ), qBlue ( myRgb ), newTransparency );
1656
+ QRgb* myLineBuffer = ( QRgb* ) transparentImageCopy->scanLine ( myHeightRunner );
1657
+ for ( int myWidthRunner = 0 ; myWidthRunner < myWidth; myWidthRunner++ )
1658
+ {
1659
+ myRgb = image->pixel ( myWidthRunner, myHeightRunner );
1660
+ // combine transparency from WMS and layer transparency
1661
+ newTransparency = ( double ) mTransparencyLevel / 255.0 * ( double )( qAlpha ( myRgb ) );
1662
+ myLineBuffer[ myWidthRunner ] = qRgba ( qRed ( myRgb ), qGreen ( myRgb ), qBlue ( myRgb ), newTransparency );
1663
+ }
1653
1664
}
1654
1665
}
1655
- }
1656
1666
1657
- // Since GDAL's RasterIO can't handle floating point, we have to round to
1658
- // the nearest pixel. Add 0.5 to get rounding instead of truncation
1659
- // out of static_cast<int>.
1660
- theQPainter->drawImage ( static_cast <int >(
1661
- myRasterViewPort->topLeftPoint .x ()
1662
- + 0.5 // try simulating rounding instead of truncation, to avoid off-by-one errors
1663
- // TODO: Check for rigorous correctness
1664
- ),
1665
- static_cast <int >(
1666
- myRasterViewPort->topLeftPoint .y ()
1667
- + 0.5 // try simulating rounding instead of truncation, to avoid off-by-one errors
1668
- // TODO: Check for rigorous correctness
1669
- ),
1670
- *image );
1671
-
1672
- if ( mTransparencyLevel != 255 )
1673
- {
1674
- delete image;
1675
- }
1667
+ theQPainter->drawImage ( myRasterViewPort->topLeftPoint .x (), myRasterViewPort->topLeftPoint .y () + currentPixelOffsetY, *image );
1668
+ currentPixelOffsetY += numRowsPerPart;
1669
+
1670
+ if ( mTransparencyLevel != 255 )
1671
+ {
1672
+ delete image;
1673
+ }
1676
1674
1677
- emit statusChanged ( tr ( " %1 retrieved using %2" ).arg ( name () ).arg ( mProviderKey ) );
1675
+ emit statusChanged ( tr ( " %1 retrieved using %2" ).arg ( name () ).arg ( mProviderKey ) );
1676
+ }
1678
1677
}
1679
1678
else
1680
1679
{
@@ -4329,6 +4328,7 @@ void QgsRasterLayer::drawMultiBandColor( QPainter * theQPainter, QgsRasterViewPo
4329
4328
{
4330
4329
return ;
4331
4330
}
4331
+
4332
4332
GDALRasterBandH myGdalRedBand = GDALGetRasterBand ( mGdalDataset , myRedBandNo );
4333
4333
GDALRasterBandH myGdalGreenBand = GDALGetRasterBand ( mGdalDataset , myGreenBandNo );
4334
4334
GDALRasterBandH myGdalBlueBand = GDALGetRasterBand ( mGdalDataset , myBlueBandNo );
@@ -4337,26 +4337,19 @@ void QgsRasterLayer::drawMultiBandColor( QPainter * theQPainter, QgsRasterViewPo
4337
4337
GDALDataType myGreenType = GDALGetRasterDataType ( myGdalGreenBand );
4338
4338
GDALDataType myBlueType = GDALGetRasterDataType ( myGdalBlueBand );
4339
4339
4340
- void *myGdalRedData = readData ( myGdalRedBand, theRasterViewPort );
4341
- void *myGdalGreenData = readData ( myGdalGreenBand, theRasterViewPort );
4342
- void *myGdalBlueData = readData ( myGdalBlueBand, theRasterViewPort );
4343
-
4344
- /* Check for out of memory error */
4345
- if ( myGdalRedData == NULL || myGdalGreenData == NULL || myGdalBlueData == NULL )
4346
- {
4347
- // Safe to free NULL-pointer */
4348
- VSIFree ( myGdalRedData );
4349
- VSIFree ( myGdalGreenData );
4350
- VSIFree ( myGdalBlueData );
4351
- return ;
4352
- }
4340
+ QRgb* redImageScanLine = 0 ;
4341
+ void * redRasterScanLine = 0 ;
4342
+ QRgb* greenImageScanLine = 0 ;
4343
+ void * greenRasterScanLine = 0 ;
4344
+ QRgb* blueImageScanLine = 0 ;
4345
+ void * blueRasterScanLine = 0 ;
4353
4346
4354
- QImage myQImage = QImage ( theRasterViewPort->drawableAreaXDim , theRasterViewPort->drawableAreaYDim , QImage::Format_ARGB32 );
4355
4347
QRgb myDefaultColor = qRgba ( 255 , 255 , 255 , 0 );
4356
4348
4357
4349
QgsRasterBandStats myRedBandStats;
4358
4350
QgsRasterBandStats myGreenBandStats;
4359
4351
QgsRasterBandStats myBlueBandStats;
4352
+
4360
4353
/*
4361
4354
* If a stetch is requested and there are no user defined Min Max values
4362
4355
* we need to get these values from the bands themselves.
@@ -4408,35 +4401,40 @@ void QgsRasterLayer::drawMultiBandColor( QPainter * theQPainter, QgsRasterViewPo
4408
4401
QgsContrastEnhancement* myGreenContrastEnhancement = contrastEnhancement ( myGreenBandNo );
4409
4402
QgsContrastEnhancement* myBlueContrastEnhancement = contrastEnhancement ( myBlueBandNo );
4410
4403
4411
- QgsDebugMsg ( " Starting main render loop" );
4412
- for ( int myRow = 0 ; myRow < theRasterViewPort->drawableAreaYDim ; ++myRow )
4404
+ QgsRasterImageBuffer redImageBuffer ( myGdalRedBand, theQPainter, theRasterViewPort, theQgsMapToPixel, &mGeoTransform [0 ] );
4405
+ redImageBuffer.reset ();
4406
+ QgsRasterImageBuffer greenImageBuffer ( myGdalGreenBand, theQPainter, theRasterViewPort, theQgsMapToPixel, &mGeoTransform [0 ] );
4407
+ greenImageBuffer.setWritingEnabled ( false ); // only draw to redImageBuffer
4408
+ greenImageBuffer.reset ();
4409
+ QgsRasterImageBuffer blueImageBuffer ( myGdalGreenBand, theQPainter, theRasterViewPort, theQgsMapToPixel, &mGeoTransform [0 ] );
4410
+ blueImageBuffer.setWritingEnabled ( false ); // only draw to redImageBuffer
4411
+ blueImageBuffer.reset ();
4412
+
4413
+ while ( redImageBuffer.nextScanLine ( &redImageScanLine, &redRasterScanLine ) && greenImageBuffer.nextScanLine ( &greenImageScanLine, &greenRasterScanLine ) \
4414
+ && blueImageBuffer.nextScanLine ( &blueImageScanLine, &blueRasterScanLine ) )
4413
4415
{
4414
- QRgb* myLineBuffer = ( QRgb* )myQImage.scanLine ( myRow );
4415
- for ( int myColumn = 0 ; myColumn < theRasterViewPort->drawableAreaXDim ; ++myColumn )
4416
+ for ( int i = 0 ; i < theRasterViewPort->drawableAreaXDim ; ++i )
4416
4417
{
4417
- myRedValue = readValue ( myGdalRedData, ( GDALDataType )myRedType,
4418
- myRow * theRasterViewPort->drawableAreaXDim + myColumn );
4419
- myGreenValue = readValue ( myGdalGreenData, ( GDALDataType )myGreenType,
4420
- myRow * theRasterViewPort->drawableAreaXDim + myColumn );
4421
- myBlueValue = readValue ( myGdalBlueData, ( GDALDataType )myBlueType,
4422
- myRow * theRasterViewPort->drawableAreaXDim + myColumn );
4418
+ myRedValue = readValue ( redImageScanLine, ( GDALDataType )myRedType, i );
4419
+ myGreenValue = readValue ( greenImageScanLine, ( GDALDataType )myGreenType, i );
4420
+ myBlueValue = readValue ( blueImageScanLine, ( GDALDataType )myBlueType, i );
4423
4421
4424
4422
if ( mValidNoDataValue && (( fabs ( myRedValue - mNoDataValue ) <= TINY_VALUE || myRedValue != myRedValue ) || ( fabs ( myGreenValue - mNoDataValue ) <= TINY_VALUE || myGreenValue != myGreenValue ) || ( fabs ( myBlueValue - mNoDataValue ) <= TINY_VALUE || myBlueValue != myBlueValue ) ) )
4425
4423
{
4426
- myLineBuffer[ myColumn ] = myDefaultColor;
4424
+ redImageScanLine[ i ] = myDefaultColor;
4427
4425
continue ;
4428
4426
}
4429
4427
4430
4428
if ( !myRedContrastEnhancement->isValueInDisplayableRange ( myRedValue ) || !myGreenContrastEnhancement->isValueInDisplayableRange ( myGreenValue ) || !myBlueContrastEnhancement->isValueInDisplayableRange ( myBlueValue ) )
4431
4429
{
4432
- myLineBuffer[ myColumn ] = myDefaultColor;
4430
+ redImageScanLine[ i ] = myDefaultColor;
4433
4431
continue ;
4434
4432
}
4435
4433
4436
4434
myAlphaValue = mRasterTransparency .alphaValue ( myRedValue, myGreenValue, myBlueValue, mTransparencyLevel );
4437
4435
if ( 0 == myAlphaValue )
4438
4436
{
4439
- myLineBuffer[ myColumn ] = myDefaultColor;
4437
+ redImageScanLine[ i ] = myDefaultColor;
4440
4438
continue ;
4441
4439
}
4442
4440
@@ -4451,34 +4449,9 @@ void QgsRasterLayer::drawMultiBandColor( QPainter * theQPainter, QgsRasterViewPo
4451
4449
myStretchedBlueValue = 255 - myStretchedBlueValue;
4452
4450
}
4453
4451
4454
- myLineBuffer[ myColumn ] = qRgba ( myStretchedRedValue, myStretchedGreenValue, myStretchedBlueValue, myAlphaValue );
4452
+ redImageScanLine[ i ] = qRgba ( myStretchedRedValue, myStretchedGreenValue, myStretchedBlueValue, myAlphaValue );
4455
4453
}
4456
4454
}
4457
- // free the scanline memory
4458
- CPLFree ( myGdalRedData );
4459
- CPLFree ( myGdalGreenData );
4460
- CPLFree ( myGdalBlueData );
4461
-
4462
- #ifdef QGISDEBUG
4463
- QPixmap *pm = dynamic_cast <QPixmap *>( theQPainter->device () );
4464
- if ( pm )
4465
- {
4466
- QgsDebugMsg ( " theQPainter stats: " );
4467
- QgsDebugMsg ( " width = " + QString::number ( pm->width () ) );
4468
- QgsDebugMsg ( " height = " + QString::number ( pm->height () ) );
4469
- pm->save ( " /tmp/qgis-rasterlayer-drawmultibandcolor-test-a.png" , " PNG" );
4470
- }
4471
- #endif
4472
-
4473
- paintImageToCanvas ( theQPainter, theRasterViewPort, theQgsMapToPixel, &myQImage );
4474
-
4475
- #ifdef QGISDEBUG
4476
- QgsDebugMsg ( " theQPainter->drawImage." );
4477
- if ( pm )
4478
- {
4479
- pm->save ( " /tmp/qgis-rasterlayer-drawmultibandcolor-test-b.png" , " PNG" );
4480
- }
4481
- #endif
4482
4455
}
4483
4456
4484
4457
void QgsRasterLayer::drawMultiBandSingleBandGray ( QPainter * theQPainter, QgsRasterViewPort * theRasterViewPort,
@@ -4518,69 +4491,58 @@ void QgsRasterLayer::drawPalettedSingleBandColor( QPainter * theQPainter, QgsRas
4518
4491
4519
4492
GDALRasterBandH myGdalBand = GDALGetRasterBand ( mGdalDataset , theBandNo );
4520
4493
GDALDataType myDataType = GDALGetRasterDataType ( myGdalBand );
4521
- void *myGdalScanData = readData ( myGdalBand, theRasterViewPort );
4522
4494
4523
- /* Check for out of memory error */
4524
- if ( myGdalScanData == NULL )
4525
- {
4526
- return ;
4527
- }
4495
+ QgsRasterImageBuffer imageBuffer ( myGdalBand, theQPainter, theRasterViewPort, theQgsMapToPixel, &mGeoTransform [0 ] );
4496
+ imageBuffer.reset ();
4528
4497
4529
- QImage myQImage = QImage ( theRasterViewPort-> drawableAreaXDim , theRasterViewPort-> drawableAreaYDim , QImage::Format_ARGB32 ) ;
4530
- QRgb myDefaultColor = qRgba ( 255 , 255 , 255 , 0 ) ;
4498
+ QRgb* imageScanLine = 0 ;
4499
+ void * rasterScanLine = 0 ;
4531
4500
4501
+ QRgb myDefaultColor = qRgba ( 255 , 255 , 255 , 0 );
4532
4502
double myPixelValue = 0.0 ;
4533
4503
int myRedValue = 0 ;
4534
4504
int myGreenValue = 0 ;
4535
4505
int myBlueValue = 0 ;
4536
4506
int myAlphaValue = 0 ;
4537
4507
4538
- QgsDebugMsg ( " Starting main render loop" );
4539
- for ( int myRow = 0 ; myRow < theRasterViewPort->drawableAreaYDim ; ++myRow )
4508
+ while ( imageBuffer.nextScanLine ( &imageScanLine, &rasterScanLine ) )
4540
4509
{
4541
- QRgb* myLineBuffer = ( QRgb* )myQImage.scanLine ( myRow );
4542
- for ( int myColumn = 0 ; myColumn < theRasterViewPort->drawableAreaXDim ; ++myColumn )
4510
+ for ( int i = 0 ; i < theRasterViewPort->drawableAreaXDim ; ++i )
4543
4511
{
4544
- myRedValue = 0 ;
4545
- myGreenValue = 0 ;
4546
- myBlueValue = 0 ;
4547
- myPixelValue = readValue ( myGdalScanData, ( GDALDataType )myDataType,
4548
- myRow * theRasterViewPort->drawableAreaXDim + myColumn );
4512
+ myRedValue = 0 ; myGreenValue = 0 ; myBlueValue = 0 ;
4513
+ myPixelValue = readValue ( rasterScanLine, ( GDALDataType )myDataType, i );
4549
4514
4550
4515
if ( mValidNoDataValue && ( fabs ( myPixelValue - mNoDataValue ) <= TINY_VALUE || myPixelValue != myPixelValue ) )
4551
4516
{
4552
- myLineBuffer[ myColumn ] = myDefaultColor;
4517
+ imageScanLine[ i ] = myDefaultColor;
4553
4518
continue ;
4554
4519
}
4555
4520
4556
4521
myAlphaValue = mRasterTransparency .alphaValue ( myPixelValue, mTransparencyLevel );
4557
4522
if ( 0 == myAlphaValue )
4558
4523
{
4559
- myLineBuffer[ myColumn ] = myDefaultColor;
4524
+ imageScanLine[ i ] = myDefaultColor;
4560
4525
continue ;
4561
4526
}
4562
4527
4563
4528
if ( !mRasterShader ->shade ( myPixelValue, &myRedValue, &myGreenValue, &myBlueValue ) )
4564
4529
{
4565
- myLineBuffer[ myColumn ] = myDefaultColor;
4530
+ imageScanLine[ i ] = myDefaultColor;
4566
4531
continue ;
4567
4532
}
4568
4533
4569
4534
if ( mInvertColor )
4570
4535
{
4571
4536
// Invert flag, flip blue and read
4572
- myLineBuffer[ myColumn ] = qRgba ( myBlueValue, myGreenValue, myRedValue, myAlphaValue );
4537
+ imageScanLine[ i ] = qRgba ( myBlueValue, myGreenValue, myRedValue, myAlphaValue );
4573
4538
}
4574
4539
else
4575
4540
{
4576
4541
// Normal
4577
- myLineBuffer[ myColumn ] = qRgba ( myRedValue, myGreenValue, myBlueValue, myAlphaValue );
4542
+ imageScanLine[ i ] = qRgba ( myRedValue, myGreenValue, myBlueValue, myAlphaValue );
4578
4543
}
4579
4544
}
4580
4545
}
4581
- CPLFree ( myGdalScanData );
4582
-
4583
- paintImageToCanvas ( theQPainter, theRasterViewPort, theQgsMapToPixel, &myQImage );
4584
4546
}
4585
4547
4586
4548
/* *
@@ -4606,71 +4568,62 @@ void QgsRasterLayer::drawPalettedSingleBandGray( QPainter * theQPainter, QgsRast
4606
4568
4607
4569
GDALRasterBandH myGdalBand = GDALGetRasterBand ( mGdalDataset , theBandNo );
4608
4570
GDALDataType myDataType = GDALGetRasterDataType ( myGdalBand );
4609
- void *myGdalScanData = readData ( myGdalBand, theRasterViewPort );
4610
4571
4611
- /* Check for out of memory error */
4612
- if ( myGdalScanData == NULL )
4613
- {
4614
- return ;
4615
- }
4572
+ QgsRasterImageBuffer imageBuffer ( myGdalBand, theQPainter, theRasterViewPort, theQgsMapToPixel, &mGeoTransform [0 ] );
4573
+ imageBuffer.reset ();
4616
4574
4617
- QImage myQImage = QImage ( theRasterViewPort-> drawableAreaXDim , theRasterViewPort-> drawableAreaYDim , QImage::Format_ARGB32 ) ;
4618
- QRgb myDefaultColor = qRgba ( 255 , 255 , 255 , 0 ) ;
4575
+ QRgb* imageScanLine = 0 ;
4576
+ void * rasterScanLine = 0 ;
4619
4577
4578
+ QRgb myDefaultColor = qRgba ( 255 , 255 , 255 , 0 );
4620
4579
double myPixelValue = 0.0 ;
4621
4580
int myRedValue = 0 ;
4622
4581
int myGreenValue = 0 ;
4623
4582
int myBlueValue = 0 ;
4624
4583
int myAlphaValue = 0 ;
4625
4584
4626
- QgsDebugMsg ( " Starting main render loop" );
4627
- for ( int myRow = 0 ; myRow < theRasterViewPort->drawableAreaYDim ; ++myRow )
4585
+ while ( imageBuffer.nextScanLine ( &imageScanLine, &rasterScanLine ) )
4628
4586
{
4629
- QRgb* myLineBuffer = ( QRgb* )myQImage.scanLine ( myRow );
4630
- for ( int myColumn = 0 ; myColumn < theRasterViewPort->drawableAreaXDim ; ++myColumn )
4587
+ for ( int i = 0 ; i < theRasterViewPort->drawableAreaXDim ; ++i )
4631
4588
{
4632
4589
myRedValue = 0 ;
4633
4590
myGreenValue = 0 ;
4634
4591
myBlueValue = 0 ;
4635
- myPixelValue = readValue ( myGdalScanData, ( GDALDataType )myDataType,
4636
- myRow * theRasterViewPort->drawableAreaXDim + myColumn );
4592
+ myPixelValue = readValue ( rasterScanLine, ( GDALDataType )myDataType, i );
4637
4593
4638
4594
if ( mValidNoDataValue && ( fabs ( myPixelValue - mNoDataValue ) <= TINY_VALUE || myPixelValue != myPixelValue ) )
4639
4595
{
4640
- myLineBuffer[ myColumn ] = myDefaultColor;
4596
+ imageScanLine[ i ] = myDefaultColor;
4641
4597
continue ;
4642
4598
}
4643
4599
4644
4600
myAlphaValue = mRasterTransparency .alphaValue ( myPixelValue, mTransparencyLevel );
4645
4601
if ( 0 == myAlphaValue )
4646
4602
{
4647
- myLineBuffer[ myColumn ] = myDefaultColor;
4603
+ imageScanLine[ i ] = myDefaultColor;
4648
4604
continue ;
4649
4605
}
4650
4606
4651
4607
if ( !mRasterShader ->shade ( myPixelValue, &myRedValue, &myGreenValue, &myBlueValue ) )
4652
4608
{
4653
- myLineBuffer[ myColumn ] = myDefaultColor;
4609
+ imageScanLine[ i ] = myDefaultColor;
4654
4610
continue ;
4655
4611
}
4656
4612
4657
4613
if ( mInvertColor )
4658
4614
{
4659
4615
// Invert flag, flip blue and read
4660
4616
double myGrayValue = ( 0.3 * ( double )myRedValue ) + ( 0.59 * ( double )myGreenValue ) + ( 0.11 * ( double )myBlueValue );
4661
- myLineBuffer[ myColumn ] = qRgba (( int )myGrayValue, ( int )myGrayValue, ( int )myGrayValue, myAlphaValue );
4617
+ imageScanLine[ i ] = qRgba (( int )myGrayValue, ( int )myGrayValue, ( int )myGrayValue, myAlphaValue );
4662
4618
}
4663
4619
else
4664
4620
{
4665
4621
// Normal
4666
4622
double myGrayValue = ( 0.3 * ( double )myBlueValue ) + ( 0.59 * ( double )myGreenValue ) + ( 0.11 * ( double )myRedValue );
4667
- myLineBuffer[ myColumn ] = qRgba (( int )myGrayValue, ( int )myGrayValue, ( int )myGrayValue, myAlphaValue );
4623
+ imageScanLine[ i ] = qRgba (( int )myGrayValue, ( int )myGrayValue, ( int )myGrayValue, myAlphaValue );
4668
4624
}
4669
4625
}
4670
4626
}
4671
- CPLFree ( myGdalScanData );
4672
-
4673
- paintImageToCanvas ( theQPainter, theRasterViewPort, theQgsMapToPixel, &myQImage );
4674
4627
}
4675
4628
4676
4629
/* *
@@ -4694,22 +4647,14 @@ void QgsRasterLayer::drawPalettedSingleBandPseudoColor( QPainter * theQPainter,
4694
4647
QgsRasterBandStats myRasterBandStats = bandStatistics ( theBandNo );
4695
4648
GDALRasterBandH myGdalBand = GDALGetRasterBand ( mGdalDataset , theBandNo );
4696
4649
GDALDataType myDataType = GDALGetRasterDataType ( myGdalBand );
4697
- void *myGdalScanData = readData ( myGdalBand, theRasterViewPort );
4698
-
4699
- /* Check for out of memory error */
4700
- if ( myGdalScanData == NULL )
4701
- {
4702
- return ;
4703
- }
4704
4650
4705
- QImage myQImage = QImage ( theRasterViewPort-> drawableAreaXDim , theRasterViewPort-> drawableAreaYDim , QImage::Format_ARGB32 );
4706
- QRgb myDefaultColor = qRgba ( 255 , 255 , 255 , 0 );
4651
+ QgsRasterImageBuffer imageBuffer ( myGdalBand, theQPainter, theRasterViewPort, theQgsMapToPixel, & mGeoTransform [ 0 ] );
4652
+ imageBuffer. reset ( );
4707
4653
4708
- if ( NULL == mRasterShader )
4709
- {
4710
- return ;
4711
- }
4654
+ QRgb* imageScanLine = 0 ;
4655
+ void * rasterScanLine = 0 ;
4712
4656
4657
+ QRgb myDefaultColor = qRgba ( 255 , 255 , 255 , 0 );
4713
4658
double myMinimumValue = 0.0 ;
4714
4659
double myMaximumValue = 0.0 ;
4715
4660
// Use standard deviations if set, otherwise, use min max of band
@@ -4733,52 +4678,46 @@ void QgsRasterLayer::drawPalettedSingleBandPseudoColor( QPainter * theQPainter,
4733
4678
int myBlueValue = 0 ;
4734
4679
int myAlphaValue = 0 ;
4735
4680
4736
- QgsDebugMsg ( " Starting main render loop" );
4737
- for ( int myRow = 0 ; myRow < theRasterViewPort->drawableAreaYDim ; ++myRow )
4681
+ while ( imageBuffer.nextScanLine ( &imageScanLine, &rasterScanLine ) )
4738
4682
{
4739
- QRgb* myLineBuffer = ( QRgb* )myQImage.scanLine ( myRow );
4740
- for ( int myColumn = 0 ; myColumn < theRasterViewPort->drawableAreaXDim ; ++myColumn )
4683
+ for ( int i = 0 ; i < theRasterViewPort->drawableAreaXDim ; ++i )
4741
4684
{
4742
4685
myRedValue = 0 ;
4743
4686
myGreenValue = 0 ;
4744
4687
myBlueValue = 0 ;
4745
- myPixelValue = readValue ( myGdalScanData, ( GDALDataType )myDataType,
4746
- myRow * theRasterViewPort->drawableAreaXDim + myColumn );
4688
+ myPixelValue = readValue ( rasterScanLine, ( GDALDataType )myDataType, i );
4747
4689
4748
4690
if ( mValidNoDataValue && ( fabs ( myPixelValue - mNoDataValue ) <= TINY_VALUE || myPixelValue != myPixelValue ) )
4749
4691
{
4750
- myLineBuffer[ myColumn ] = myDefaultColor;
4692
+ imageScanLine[ i ] = myDefaultColor;
4751
4693
continue ;
4752
4694
}
4753
4695
4754
4696
myAlphaValue = mRasterTransparency .alphaValue ( myPixelValue, mTransparencyLevel );
4755
4697
if ( 0 == myAlphaValue )
4756
4698
{
4757
- myLineBuffer[ myColumn ] = myDefaultColor;
4699
+ imageScanLine[ i ] = myDefaultColor;
4758
4700
continue ;
4759
4701
}
4760
4702
4761
4703
if ( !mRasterShader ->shade ( myPixelValue, &myRedValue, &myGreenValue, &myBlueValue ) )
4762
4704
{
4763
- myLineBuffer[ myColumn ] = myDefaultColor;
4705
+ imageScanLine[ i ] = myDefaultColor;
4764
4706
continue ;
4765
4707
}
4766
4708
4767
4709
if ( mInvertColor )
4768
4710
{
4769
4711
// Invert flag, flip blue and read
4770
- myLineBuffer[ myColumn ] = qRgba ( myBlueValue, myGreenValue, myRedValue, myAlphaValue );
4712
+ imageScanLine[ i ] = qRgba ( myBlueValue, myGreenValue, myRedValue, myAlphaValue );
4771
4713
}
4772
4714
else
4773
4715
{
4774
4716
// Normal
4775
- myLineBuffer[ myColumn ] = qRgba ( myRedValue, myGreenValue, myBlueValue, myAlphaValue );
4717
+ imageScanLine[ i ] = qRgba ( myRedValue, myGreenValue, myBlueValue, myAlphaValue );
4776
4718
}
4777
4719
}
4778
4720
}
4779
- CPLFree ( myGdalScanData );
4780
-
4781
- paintImageToCanvas ( theQPainter, theRasterViewPort, theQgsMapToPixel, &myQImage );
4782
4721
}
4783
4722
4784
4723
/* *
@@ -4804,19 +4743,19 @@ void QgsRasterLayer::drawSingleBandGray( QPainter * theQPainter, QgsRasterViewPo
4804
4743
4805
4744
GDALRasterBandH myGdalBand = GDALGetRasterBand ( mGdalDataset , theBandNo );
4806
4745
GDALDataType myDataType = GDALGetRasterDataType ( myGdalBand );
4807
- void *myGdalScanData = readData ( myGdalBand, theRasterViewPort );
4746
+ QgsRasterImageBuffer imageBuffer ( myGdalBand, theQPainter, theRasterViewPort, theQgsMapToPixel, &mGeoTransform [0 ] );
4747
+ imageBuffer.reset ();
4808
4748
4809
- /* Check for out of memory error */
4810
- if ( myGdalScanData == NULL )
4811
- {
4812
- return ;
4813
- }
4749
+ QRgb* imageScanLine = 0 ;
4750
+ void * rasterScanLine = 0 ;
4814
4751
4815
- QImage myQImage = QImage ( theRasterViewPort->drawableAreaXDim , theRasterViewPort->drawableAreaYDim , QImage::Format_ARGB32 );
4816
4752
QRgb myDefaultColor = qRgba ( 255 , 255 , 255 , 0 );
4753
+ double myGrayValue = 0.0 ;
4754
+ int myGrayVal = 0 ;
4755
+ int myAlphaValue = 0 ;
4756
+ QgsContrastEnhancement* myContrastEnhancement = contrastEnhancement ( theBandNo );
4817
4757
4818
4758
QgsRasterBandStats myGrayBandStats;
4819
-
4820
4759
if ( QgsContrastEnhancement::NoEnhancement != contrastEnhancementAlgorithm () && !mUserDefinedGrayMinimumMaximum && mStandardDeviations > 0 )
4821
4760
{
4822
4761
mGrayMinimumMaximumEstimated = false ;
@@ -4836,41 +4775,28 @@ void QgsRasterLayer::drawSingleBandGray( QPainter * theQPainter, QgsRasterViewPo
4836
4775
4837
4776
}
4838
4777
4839
- QgsDebugMsg ( " Starting main render loop" );
4840
- // print each point in myGdalScanData with equal parts R, G, B or make it show as gray
4841
- double myGrayValue = 0.0 ;
4842
- int myGrayVal = 0 ;
4843
- int myAlphaValue = 0 ;
4844
- QgsContrastEnhancement* myContrastEnhancement = contrastEnhancement ( theBandNo );
4845
- for ( int myRow = 0 ; myRow < theRasterViewPort->drawableAreaYDim ; ++myRow )
4778
+ while ( imageBuffer.nextScanLine ( &imageScanLine, &rasterScanLine ) )
4846
4779
{
4847
- QRgb* myLineBuffer = ( QRgb* )myQImage.scanLine ( myRow );
4848
- for ( int myColumn = 0 ; myColumn < theRasterViewPort->drawableAreaXDim ; ++myColumn )
4780
+ for ( int i = 0 ; i < theRasterViewPort->drawableAreaXDim ; ++i )
4849
4781
{
4850
- myGrayValue = readValue ( myGdalScanData, myDataType,
4851
- myRow * theRasterViewPort->drawableAreaXDim + myColumn );
4852
-
4853
- // If mNoDataValue is 'nan', the comparison
4854
- // against myGrayVal will always fail ( nan==nan always
4855
- // returns false, by design), hence the slightly odd comparison
4856
- // of myGrayVal against itself.
4782
+ myGrayValue = readValue ( rasterScanLine, ( GDALDataType )myDataType, i );
4857
4783
4858
4784
if ( mValidNoDataValue && ( fabs ( myGrayValue - mNoDataValue ) <= TINY_VALUE || myGrayValue != myGrayValue ) )
4859
4785
{
4860
- myLineBuffer[ myColumn ] = myDefaultColor;
4786
+ imageScanLine[ i ] = myDefaultColor;
4861
4787
continue ;
4862
4788
}
4863
4789
4864
4790
if ( !myContrastEnhancement->isValueInDisplayableRange ( myGrayValue ) )
4865
4791
{
4866
- myLineBuffer[ myColumn ] = myDefaultColor;
4792
+ imageScanLine[ i ] = myDefaultColor;
4867
4793
continue ;
4868
4794
}
4869
4795
4870
4796
myAlphaValue = mRasterTransparency .alphaValue ( myGrayValue, mTransparencyLevel );
4871
4797
if ( 0 == myAlphaValue )
4872
4798
{
4873
- myLineBuffer[ myColumn ] = myDefaultColor;
4799
+ imageScanLine[ i ] = myDefaultColor;
4874
4800
continue ;
4875
4801
}
4876
4802
@@ -4882,16 +4808,9 @@ void QgsRasterLayer::drawSingleBandGray( QPainter * theQPainter, QgsRasterViewPo
4882
4808
myGrayVal = 255 - myGrayVal;
4883
4809
}
4884
4810
4885
- myLineBuffer[ myColumn ] = qRgba ( myGrayVal, myGrayVal, myGrayVal, myAlphaValue );
4811
+ imageScanLine[ i ] = qRgba ( myGrayVal, myGrayVal, myGrayVal, myAlphaValue );
4886
4812
}
4887
4813
}
4888
-
4889
- CPLFree ( myGdalScanData );
4890
-
4891
- QgsDebugMsg ( " Render done, preparing to copy to canvas" );
4892
-
4893
- paintImageToCanvas ( theQPainter, theRasterViewPort, theQgsMapToPixel, &myQImage );
4894
-
4895
4814
} // QgsRasterLayer::drawSingleBandGray
4896
4815
4897
4816
void QgsRasterLayer::drawSingleBandPseudoColor ( QPainter * theQPainter,
@@ -4909,17 +4828,14 @@ void QgsRasterLayer::drawSingleBandPseudoColor( QPainter * theQPainter,
4909
4828
QgsRasterBandStats myRasterBandStats = bandStatistics ( theBandNo );
4910
4829
GDALRasterBandH myGdalBand = GDALGetRasterBand ( mGdalDataset , theBandNo );
4911
4830
GDALDataType myDataType = GDALGetRasterDataType ( myGdalBand );
4912
- void *myGdalScanData = readData ( myGdalBand, theRasterViewPort );
4913
4831
4914
- /* Check for out of memory error */
4915
- if ( myGdalScanData == NULL )
4916
- {
4917
- return ;
4918
- }
4832
+ QgsRasterImageBuffer imageBuffer ( myGdalBand, theQPainter, theRasterViewPort, theQgsMapToPixel, &mGeoTransform [0 ] );
4833
+ imageBuffer.reset ();
4919
4834
4920
- QImage myQImage = QImage ( theRasterViewPort-> drawableAreaXDim , theRasterViewPort-> drawableAreaYDim , QImage::Format_ARGB32 ) ;
4921
- QRgb myDefaultColor = qRgba ( 255 , 255 , 255 , 0 ) ;
4835
+ QRgb* imageScanLine = 0 ;
4836
+ void * rasterScanLine = 0 ;
4922
4837
4838
+ QRgb myDefaultColor = qRgba ( 255 , 255 , 255 , 0 );
4923
4839
if ( NULL == mRasterShader )
4924
4840
{
4925
4841
return ;
@@ -4942,57 +4858,50 @@ void QgsRasterLayer::drawSingleBandPseudoColor( QPainter * theQPainter,
4942
4858
mRasterShader ->setMinimumValue ( myMinimumValue );
4943
4859
mRasterShader ->setMaximumValue ( myMaximumValue );
4944
4860
4945
-
4946
4861
int myRedValue = 255 ;
4947
4862
int myGreenValue = 255 ;
4948
4863
int myBlueValue = 255 ;
4949
4864
4950
4865
double myPixelValue = 0.0 ;
4951
4866
int myAlphaValue = 0 ;
4952
- QgsDebugMsg ( " Starting main render loop " );
4953
- for ( int myRow = 0 ; myRow < theRasterViewPort-> drawableAreaYDim ; ++myRow )
4867
+
4868
+ while ( imageBuffer. nextScanLine ( &imageScanLine, &rasterScanLine ) )
4954
4869
{
4955
- QRgb* myLineBuffer = ( QRgb* )myQImage.scanLine ( myRow );
4956
- for ( int myColumn = 0 ; myColumn < theRasterViewPort->drawableAreaXDim ; ++myColumn )
4870
+ for ( int i = 0 ; i < theRasterViewPort->drawableAreaXDim ; ++i )
4957
4871
{
4958
- myPixelValue = readValue ( myGdalScanData, myDataType,
4959
- myRow * theRasterViewPort->drawableAreaXDim + myColumn );
4872
+ myPixelValue = readValue ( rasterScanLine, myDataType, i );
4960
4873
4961
4874
if ( mValidNoDataValue && ( fabs ( myPixelValue - mNoDataValue ) <= TINY_VALUE || myPixelValue != myPixelValue ) )
4962
4875
{
4963
- myLineBuffer[ myColumn ] = myDefaultColor;
4876
+ imageScanLine[ i ] = myDefaultColor;
4964
4877
continue ;
4965
4878
}
4966
4879
4967
4880
myAlphaValue = mRasterTransparency .alphaValue ( myPixelValue, mTransparencyLevel );
4968
4881
if ( 0 == myAlphaValue )
4969
4882
{
4970
- myLineBuffer[ myColumn ] = myDefaultColor;
4883
+ imageScanLine[ i ] = myDefaultColor;
4971
4884
continue ;
4972
4885
}
4973
4886
4974
4887
if ( !mRasterShader ->shade ( myPixelValue, &myRedValue, &myGreenValue, &myBlueValue ) )
4975
4888
{
4976
- myLineBuffer[ myColumn ] = myDefaultColor;
4889
+ imageScanLine[ i ] = myDefaultColor;
4977
4890
continue ;
4978
4891
}
4979
4892
4980
4893
if ( mInvertColor )
4981
4894
{
4982
4895
// Invert flag, flip blue and read
4983
- myLineBuffer[ myColumn ] = qRgba ( myBlueValue, myGreenValue, myRedValue, myAlphaValue );
4896
+ imageScanLine[ i ] = qRgba ( myBlueValue, myGreenValue, myRedValue, myAlphaValue );
4984
4897
}
4985
4898
else
4986
4899
{
4987
4900
// Normal
4988
- myLineBuffer[ myColumn ] = qRgba ( myRedValue, myGreenValue, myBlueValue, myAlphaValue );
4901
+ imageScanLine[ i ] = qRgba ( myRedValue, myGreenValue, myBlueValue, myAlphaValue );
4989
4902
}
4990
- } // end of columnwise loop
4991
- } // end of rowwise loop
4992
-
4993
- CPLFree ( myGdalScanData );
4994
-
4995
- paintImageToCanvas ( theQPainter, theRasterViewPort, theQgsMapToPixel, &myQImage );
4903
+ }
4904
+ }
4996
4905
}
4997
4906
4998
4907
@@ -5085,7 +4994,7 @@ void QgsRasterLayer::paintImageToCanvas( QPainter* theQPainter, QgsRasterViewPor
5085
4994
5086
4995
// Catch special rendering cases
5087
4996
// INSTANCE: 1x1
5088
- if ( 1 == theRasterViewPort->clippedWidth && 1 == theRasterViewPort->clippedHeight )
4997
+ if ( 1 == theRasterViewPort->clippedWidth && 1 == theRasterViewPort->clippedHeight )
5089
4998
{
5090
4999
QColor myColor ( theImage->pixel ( 0 , 0 ) );
5091
5000
myColor.setAlpha ( qAlpha ( theImage->pixel ( 0 , 0 ) ) );
@@ -5096,38 +5005,41 @@ void QgsRasterLayer::paintImageToCanvas( QPainter* theQPainter, QgsRasterViewPor
5096
5005
QBrush ( myColor ) );
5097
5006
}
5098
5007
// 1x2, 2x1 or 2x2
5099
- else if ( 2 >= theRasterViewPort->clippedWidth && 2 >= theRasterViewPort->clippedHeight )
5008
+ else if ( 2 >= theRasterViewPort->clippedWidth && 2 >= theRasterViewPort->clippedHeight )
5100
5009
{
5101
5010
int myPixelBoundaryX = 0 ;
5102
5011
int myPixelBoundaryY = 0 ;
5103
- if ( theQgsMapToPixel ) {
5104
- myPixelBoundaryX = static_cast <int >( theRasterViewPort->topLeftPoint .x () + 0.5 ) + static_cast <int >( fabs ( mGeoTransform [1 ] / theQgsMapToPixel->mapUnitsPerPixel () ) ) - paintXoffset;
5105
- myPixelBoundaryY = static_cast <int >( theRasterViewPort->topLeftPoint .y () + 0.5 ) + static_cast <int >( fabs (mGeoTransform [5 ] / theQgsMapToPixel->mapUnitsPerPixel () )) - paintYoffset;
5012
+ if ( theQgsMapToPixel )
5013
+ {
5014
+ myPixelBoundaryX = static_cast <int >( theRasterViewPort->topLeftPoint .x () + 0.5 ) + static_cast <int >( fabs ( mGeoTransform [1 ] / theQgsMapToPixel->mapUnitsPerPixel () ) ) - paintXoffset;
5015
+ myPixelBoundaryY = static_cast <int >( theRasterViewPort->topLeftPoint .y () + 0.5 ) + static_cast <int >( fabs ( mGeoTransform [5 ] / theQgsMapToPixel->mapUnitsPerPixel () ) ) - paintYoffset;
5106
5016
}
5107
5017
5108
5018
// INSTANCE: 1x2
5109
- if ( 1 == theRasterViewPort->clippedWidth ) {
5019
+ if ( 1 == theRasterViewPort->clippedWidth )
5020
+ {
5110
5021
QColor myColor ( theImage->pixel ( 0 , 0 ) );
5111
5022
myColor.setAlpha ( qAlpha ( theImage->pixel ( 0 , 0 ) ) );
5112
5023
theQPainter->fillRect ( static_cast <int >( theRasterViewPort->topLeftPoint .x () + 0.5 ),
5113
5024
static_cast <int >( theRasterViewPort->topLeftPoint .y () + 0.5 ),
5114
5025
static_cast <int >( theRasterViewPort->bottomRightPoint .x () ),
5115
5026
static_cast <int >( myPixelBoundaryY ),
5116
5027
QBrush ( myColor ) );
5117
- myColor = QColor ( theImage->pixel ( 0 , 1 ) );
5028
+ myColor = QColor ( theImage->pixel ( 0 , 1 ) );
5118
5029
myColor.setAlpha ( qAlpha ( theImage->pixel ( 0 , 1 ) ) );
5119
5030
theQPainter->fillRect ( static_cast <int >( theRasterViewPort->topLeftPoint .x () + 0.5 ),
5120
5031
static_cast <int >( myPixelBoundaryY ),
5121
5032
static_cast <int >( theRasterViewPort->bottomRightPoint .x () ),
5122
5033
static_cast <int >( theRasterViewPort->bottomRightPoint .y () ),
5123
5034
QBrush ( myColor ) );
5124
5035
}
5125
- else {
5036
+ else
5037
+ {
5126
5038
// INSTANCE: 2x1
5127
- if ( 1 == theRasterViewPort->clippedHeight )
5039
+ if ( 1 == theRasterViewPort->clippedHeight )
5128
5040
{
5129
5041
QColor myColor ( theImage->pixel ( 0 , 0 ) );
5130
- myColor.setAlpha ( qAlpha ( theImage->pixel ( 0 ,0 ) ) );
5042
+ myColor.setAlpha ( qAlpha ( theImage->pixel ( 0 , 0 ) ) );
5131
5043
theQPainter->fillRect ( static_cast <int >( theRasterViewPort->topLeftPoint .x () + 0.5 ),
5132
5044
static_cast <int >( theRasterViewPort->topLeftPoint .y () + 0.5 ),
5133
5045
static_cast <int >( myPixelBoundaryX ),
@@ -5148,10 +5060,10 @@ void QgsRasterLayer::paintImageToCanvas( QPainter* theQPainter, QgsRasterViewPor
5148
5060
myColor.setAlpha ( qAlpha ( theImage->pixel ( 0 , 0 ) ) );
5149
5061
theQPainter->fillRect ( static_cast <int >( theRasterViewPort->topLeftPoint .x () + 0.5 ),
5150
5062
static_cast <int >( theRasterViewPort->topLeftPoint .y () + 0.5 ),
5151
- static_cast <int >(myPixelBoundaryX ),
5063
+ static_cast <int >( myPixelBoundaryX ),
5152
5064
static_cast <int >( myPixelBoundaryY ),
5153
5065
QBrush ( myColor ) );
5154
- myColor = QColor ( theImage->pixel ( 1 , 0 ) );
5066
+ myColor = QColor ( theImage->pixel ( 1 , 0 ) );
5155
5067
myColor.setAlpha ( qAlpha ( theImage->pixel ( 1 , 0 ) ) );
5156
5068
theQPainter->fillRect ( static_cast <int >( myPixelBoundaryX ),
5157
5069
static_cast <int >( theRasterViewPort->topLeftPoint .y () + 0.5 ),
@@ -5177,7 +5089,8 @@ void QgsRasterLayer::paintImageToCanvas( QPainter* theQPainter, QgsRasterViewPor
5177
5089
5178
5090
}
5179
5091
// INSTANCE: > 2x2, so just use the image filled by GDAL
5180
- else {
5092
+ else
5093
+ {
5181
5094
theQPainter->drawImage ( static_cast <int >( theRasterViewPort->topLeftPoint .x () + 0.5 ),
5182
5095
static_cast <int >( theRasterViewPort->topLeftPoint .y () + 0.5 ),
5183
5096
*theImage,
@@ -5617,3 +5530,297 @@ QString QgsRasterLayer::validateBandName( QString const & theBandName )
5617
5530
QgsDebugMsg ( " All checks failed, returning '" + QSTRING_NOT_SET + " '" );
5618
5531
return TRSTRING_NOT_SET;
5619
5532
}
5533
+
5534
+ QgsRasterImageBuffer::QgsRasterImageBuffer ( GDALRasterBandH rasterBand, QPainter* p, QgsRasterViewPort* viewPort, const QgsMapToPixel* mapToPixel, double * geoTransform ): \
5535
+ mRasterBand( rasterBand ), mPainter( p ), mViewPort( viewPort ), mMapToPixel( mapToPixel ), mValid( false ), mWritingEnabled( true ), mDrawPixelRect( false ), mCurrentImage( 0 ), mCurrentGDALData( 0 ), mGeoTransform( geoTransform )
5536
+ {
5537
+
5538
+ }
5539
+
5540
+ QgsRasterImageBuffer::~QgsRasterImageBuffer ()
5541
+ {
5542
+ delete mCurrentImage ;
5543
+ CPLFree ( mCurrentGDALData );
5544
+ }
5545
+
5546
+ void QgsRasterImageBuffer::reset ( int maxPixelsInVirtualMemory )
5547
+ {
5548
+ if ( mRasterBand && mPainter && mViewPort && mMapToPixel )
5549
+ {
5550
+ mValid = true ;
5551
+ }
5552
+ else
5553
+ {
5554
+ mValid = false ;
5555
+ return ;
5556
+ }
5557
+
5558
+ // decide on the partition of the image
5559
+
5560
+ int pixels = mViewPort ->drawableAreaXDim * mViewPort ->drawableAreaYDim ;
5561
+ int mNumPartImages = pixels / maxPixelsInVirtualMemory + 1.0 ;
5562
+ mNumRasterRowsPerPart = ( double )mViewPort ->clippedHeight / ( double )mNumPartImages + 0.5 ;
5563
+
5564
+ mCurrentPartRasterMin = -1 ;
5565
+ mCurrentPartRasterMax = -1 ;
5566
+ mCurrentPartImageRow = 0 ;
5567
+ mNumCurrentImageRows = 0 ;
5568
+
5569
+ createNextPartImage ();
5570
+
5571
+ if ( 2 >= mViewPort ->clippedWidth && 2 >= mViewPort ->clippedHeight )
5572
+ {
5573
+ // use Peter's fix for zoomed in rasters
5574
+ mDrawPixelRect = true ;
5575
+ }
5576
+ }
5577
+
5578
+ bool QgsRasterImageBuffer::nextScanLine ( QRgb** imageScanLine, void ** rasterScanLine )
5579
+ {
5580
+ if ( !mValid )
5581
+ {
5582
+ return false ;
5583
+ }
5584
+
5585
+ if ( !mCurrentGDALData || ! mCurrentImage )
5586
+ {
5587
+ return false ;
5588
+ }
5589
+
5590
+ if ( mCurrentPartImageRow >= ( mNumCurrentImageRows ) )
5591
+ {
5592
+ if ( !createNextPartImage () )
5593
+ {
5594
+ return false ;
5595
+ }
5596
+ }
5597
+
5598
+ if ( mWritingEnabled )
5599
+ {
5600
+ *imageScanLine = ( QRgb* )( mCurrentImage ->scanLine ( mCurrentPartImageRow ) );
5601
+ }
5602
+ else
5603
+ {
5604
+ *imageScanLine = 0 ;
5605
+ }
5606
+ GDALDataType type = GDALGetRasterDataType ( mRasterBand );
5607
+ int size = GDALGetDataTypeSize ( type ) / 8 ;
5608
+ *rasterScanLine = mCurrentGDALData + mCurrentPartImageRow * mViewPort ->drawableAreaXDim * size;
5609
+
5610
+ ++mCurrentPartImageRow ;
5611
+ ++mCurrentRow ;
5612
+ return true ;
5613
+ }
5614
+
5615
+ bool QgsRasterImageBuffer::createNextPartImage ()
5616
+ {
5617
+ // draw the last image if mCurrentImage if it exists
5618
+ if ( mCurrentImage )
5619
+ {
5620
+ if ( mWritingEnabled )
5621
+ {
5622
+ if ( 2 >= mViewPort ->clippedWidth && 2 >= mViewPort ->clippedHeight )
5623
+ {
5624
+ drawPixelRectangle ();
5625
+ }
5626
+ else
5627
+ {
5628
+ double xLeft = mViewPort ->topLeftPoint .x ();
5629
+ double yTop = mViewPort ->topLeftPoint .y () + fabs ( mGeoTransform [5 ] ) * mCurrentPartRasterMin / mMapToPixel ->mapUnitsPerPixel ();
5630
+ mPainter ->drawImage ( QPointF ( xLeft, yTop + 0.5 ), *mCurrentImage );
5631
+ }
5632
+ }
5633
+ }
5634
+
5635
+ delete mCurrentImage ; mCurrentImage = 0 ;
5636
+ CPLFree ( mCurrentGDALData ); mCurrentGDALData = 0 ;
5637
+
5638
+ if ( mCurrentPartRasterMax >= mViewPort ->clippedHeight )
5639
+ {
5640
+ return false ; // already at the end...
5641
+ }
5642
+
5643
+ mCurrentPartRasterMin = mCurrentPartRasterMax + 1 ;
5644
+ mCurrentPartRasterMax = mCurrentPartRasterMin + mNumRasterRowsPerPart ;
5645
+ if ( mCurrentPartRasterMax > mViewPort ->clippedHeight )
5646
+ {
5647
+ mCurrentPartRasterMax = mViewPort ->clippedHeight ;
5648
+ }
5649
+ mCurrentRow = mCurrentPartRasterMin ;
5650
+ mCurrentPartImageRow = 0 ;
5651
+
5652
+ // read GDAL image data
5653
+ GDALDataType type = GDALGetRasterDataType ( mRasterBand );
5654
+ int size = GDALGetDataTypeSize ( type ) / 8 ;
5655
+ int xSize = mViewPort ->drawableAreaXDim ;
5656
+
5657
+ // make the raster tiles overlap at least 2 pixels to avoid white stripes
5658
+ int overlapRows = 0 ;
5659
+ overlapRows = mMapToPixel ->mapUnitsPerPixel () / fabs ( mGeoTransform [5 ] ) + 2 ;
5660
+ if ( mCurrentPartRasterMax + overlapRows >= mViewPort ->clippedHeight )
5661
+ {
5662
+ overlapRows = 0 ;
5663
+ }
5664
+ int rasterYSize = mCurrentPartRasterMax - mCurrentPartRasterMin + overlapRows;
5665
+
5666
+ int ySize = 0 ;
5667
+ if ( 2 >= mViewPort ->clippedWidth && 2 >= mViewPort ->clippedHeight ) // for zoomed in rasters
5668
+ {
5669
+ rasterYSize = mViewPort ->clippedHeight ;
5670
+ ySize = mViewPort ->drawableAreaYDim ;
5671
+ }
5672
+ else // normal mode
5673
+ {
5674
+ ySize = fabs ((( rasterYSize ) / mMapToPixel ->mapUnitsPerPixel () * mGeoTransform [5 ] ) ) + 0.5 ;
5675
+ }
5676
+ if ( ySize == 0 )
5677
+ {
5678
+ return false ;
5679
+ }
5680
+ mNumCurrentImageRows = ySize;
5681
+ mCurrentGDALData = VSIMalloc ( size * xSize * ySize );
5682
+ CPLErr myErr = GDALRasterIO ( mRasterBand , GF_Read, mViewPort ->rectXOffset , \
5683
+ mViewPort ->rectYOffset + mCurrentRow , mViewPort ->clippedWidth , rasterYSize, \
5684
+ mCurrentGDALData , xSize, ySize, type, 0 , 0 );
5685
+
5686
+ if ( myErr != CPLE_None )
5687
+ {
5688
+ CPLFree ( mCurrentGDALData );
5689
+ mCurrentGDALData = 0 ;
5690
+ return false ;
5691
+ }
5692
+
5693
+ // create the QImage
5694
+ if ( mWritingEnabled )
5695
+ {
5696
+ mCurrentImage = new QImage ( xSize, ySize, QImage::Format_ARGB32 );
5697
+ mCurrentImage ->fill ( qRgba ( 255 , 255 , 255 , 0 ) );
5698
+ }
5699
+ else
5700
+ {
5701
+ mCurrentImage = 0 ;
5702
+ }
5703
+ return true ;
5704
+ }
5705
+
5706
+ void QgsRasterImageBuffer::drawPixelRectangle ()
5707
+ {
5708
+ // Set up the initial offset into the myQImage we want to copy to the map canvas
5709
+ // This is useful when the source image pixels are larger than the screen image.
5710
+ int paintXoffset = 0 ;
5711
+ int paintYoffset = 0 ;
5712
+
5713
+ if ( mMapToPixel )
5714
+ {
5715
+ paintXoffset = static_cast <int >(
5716
+ ( mViewPort ->rectXOffsetFloat -
5717
+ mViewPort ->rectXOffset )
5718
+ / mMapToPixel ->mapUnitsPerPixel ()
5719
+ * fabs ( mGeoTransform [1 ] )
5720
+ );
5721
+
5722
+ paintYoffset = static_cast <int >(
5723
+ ( mViewPort ->rectYOffsetFloat -
5724
+ mViewPort ->rectYOffset )
5725
+ / mMapToPixel ->mapUnitsPerPixel ()
5726
+ * fabs ( mGeoTransform [5 ] )
5727
+ );
5728
+ }
5729
+
5730
+ // fix for zoomed in rasters
5731
+ // Catch special rendering cases
5732
+ // INSTANCE: 1x1
5733
+ if ( 1 == mViewPort ->clippedWidth && 1 == mViewPort ->clippedHeight )
5734
+ {
5735
+ QColor myColor ( mCurrentImage ->pixel ( 0 , 0 ) );
5736
+ myColor.setAlpha ( qAlpha ( mCurrentImage ->pixel ( 0 , 0 ) ) );
5737
+ mPainter ->fillRect ( static_cast <int >( mViewPort ->topLeftPoint .x () + 0.5 ),
5738
+ static_cast <int >( mViewPort ->topLeftPoint .y () + 0.5 ),
5739
+ static_cast <int >( mViewPort ->bottomRightPoint .x () ),
5740
+ static_cast <int >( mViewPort ->bottomRightPoint .y () ),
5741
+ QBrush ( myColor ) );
5742
+ }
5743
+ // 1x2, 2x1 or 2x2
5744
+ else if ( 2 >= mViewPort ->clippedWidth && 2 >= mViewPort ->clippedHeight )
5745
+ {
5746
+ int myPixelBoundaryX = 0 ;
5747
+ int myPixelBoundaryY = 0 ;
5748
+ if ( mMapToPixel )
5749
+ {
5750
+ myPixelBoundaryX = static_cast <int >( mViewPort ->topLeftPoint .x () + 0.5 ) + static_cast <int >( fabs ( mGeoTransform [1 ] / mMapToPixel ->mapUnitsPerPixel () ) ) - paintXoffset;
5751
+ myPixelBoundaryY = static_cast <int >( mViewPort ->topLeftPoint .y () + 0.5 ) + static_cast <int >( fabs ( mGeoTransform [5 ] / mMapToPixel ->mapUnitsPerPixel () ) ) - paintYoffset;
5752
+ }
5753
+
5754
+ // INSTANCE: 1x2
5755
+ if ( 1 == mViewPort ->clippedWidth )
5756
+ {
5757
+ QColor myColor ( mCurrentImage ->pixel ( 0 , 0 ) );
5758
+ myColor.setAlpha ( qAlpha ( mCurrentImage ->pixel ( 0 , 0 ) ) );
5759
+ mPainter ->fillRect ( static_cast <int >( mViewPort ->topLeftPoint .x () + 0.5 ),
5760
+ static_cast <int >( mViewPort ->topLeftPoint .y () + 0.5 ),
5761
+ static_cast <int >( mViewPort ->bottomRightPoint .x () ),
5762
+ static_cast <int >( myPixelBoundaryY ),
5763
+ QBrush ( myColor ) );
5764
+ myColor = QColor ( mCurrentImage ->pixel ( 0 , 1 ) );
5765
+ myColor.setAlpha ( qAlpha ( mCurrentImage ->pixel ( 0 , 1 ) ) );
5766
+ mPainter ->fillRect ( static_cast <int >( mViewPort ->topLeftPoint .x () + 0.5 ),
5767
+ static_cast <int >( myPixelBoundaryY ),
5768
+ static_cast <int >( mViewPort ->bottomRightPoint .x () ),
5769
+ static_cast <int >( mViewPort ->bottomRightPoint .y () ),
5770
+ QBrush ( myColor ) );
5771
+ }
5772
+ else
5773
+ {
5774
+ // INSTANCE: 2x1
5775
+ if ( 1 == mViewPort ->clippedHeight )
5776
+ {
5777
+ QColor myColor ( mCurrentImage ->pixel ( 0 , 0 ) );
5778
+ myColor.setAlpha ( qAlpha ( mCurrentImage ->pixel ( 0 , 0 ) ) );
5779
+ mPainter ->fillRect ( static_cast <int >( mViewPort ->topLeftPoint .x () + 0.5 ),
5780
+ static_cast <int >( mViewPort ->topLeftPoint .y () + 0.5 ),
5781
+ static_cast <int >( myPixelBoundaryX ),
5782
+ static_cast <int >( mViewPort ->bottomRightPoint .y () ),
5783
+ QBrush ( myColor ) );
5784
+ myColor = QColor ( mCurrentImage ->pixel ( 1 , 0 ) );
5785
+ myColor.setAlpha ( qAlpha ( mCurrentImage ->pixel ( 1 , 0 ) ) );
5786
+ mPainter ->fillRect ( static_cast <int >( myPixelBoundaryX ),
5787
+ static_cast <int >( mViewPort ->topLeftPoint .y () + 0.5 ),
5788
+ static_cast <int >( mViewPort ->bottomRightPoint .x () ),
5789
+ static_cast <int >( mViewPort ->bottomRightPoint .y () ),
5790
+ QBrush ( myColor ) );
5791
+ }
5792
+ // INSTANCE: 2x2
5793
+ else
5794
+ {
5795
+ QColor myColor ( mCurrentImage ->pixel ( 0 , 0 ) );
5796
+ myColor.setAlpha ( qAlpha ( mCurrentImage ->pixel ( 0 , 0 ) ) );
5797
+ mPainter ->fillRect ( static_cast <int >( mViewPort ->topLeftPoint .x () + 0.5 ),
5798
+ static_cast <int >( mViewPort ->topLeftPoint .y () + 0.5 ),
5799
+ static_cast <int >( myPixelBoundaryX ),
5800
+ static_cast <int >( myPixelBoundaryY ),
5801
+ QBrush ( myColor ) );
5802
+ myColor = QColor ( mCurrentImage ->pixel ( 1 , 0 ) );
5803
+ myColor.setAlpha ( qAlpha ( mCurrentImage ->pixel ( 1 , 0 ) ) );
5804
+ mPainter ->fillRect ( static_cast <int >( myPixelBoundaryX ),
5805
+ static_cast <int >( mViewPort ->topLeftPoint .y () + 0.5 ),
5806
+ static_cast <int >( mViewPort ->bottomRightPoint .x () ),
5807
+ static_cast <int >( myPixelBoundaryY ),
5808
+ QBrush ( myColor ) );
5809
+ myColor = QColor ( mCurrentImage ->pixel ( 0 , 1 ) );
5810
+ myColor.setAlpha ( qAlpha ( mCurrentImage ->pixel ( 0 , 1 ) ) );
5811
+ mPainter ->fillRect ( static_cast <int >( mViewPort ->topLeftPoint .x () + 0.5 ),
5812
+ static_cast <int >( myPixelBoundaryY ),
5813
+ static_cast <int >( myPixelBoundaryX ),
5814
+ static_cast <int >( mViewPort ->bottomRightPoint .y () ),
5815
+ QBrush ( myColor ) );
5816
+ myColor = QColor ( mCurrentImage ->pixel ( 1 , 1 ) );
5817
+ myColor.setAlpha ( qAlpha ( mCurrentImage ->pixel ( 1 , 1 ) ) );
5818
+ mPainter ->fillRect ( static_cast <int >( myPixelBoundaryX ),
5819
+ static_cast <int >( myPixelBoundaryY ),
5820
+ static_cast <int >( mViewPort ->bottomRightPoint .x () ),
5821
+ static_cast <int >( mViewPort ->bottomRightPoint .y () ),
5822
+ QBrush ( myColor ) );
5823
+ }
5824
+ }
5825
+ }
5826
+ }
0 commit comments