QGIS API Documentation  3.14.0-Pi (9f7028fd23)
qgsrasterdrawer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsrasterdrawer.cpp
3  ---------------------
4  begin : June 2012
5  copyright : (C) 2012 by Radim Blazek
6  email : radim dot blazek at gmail.com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "qgslogger.h"
19 #include "qgsrasterblock.h"
20 #include "qgsrasterdrawer.h"
21 #include "qgsrasterinterface.h"
22 #include "qgsrasteriterator.h"
23 #include "qgsrasterviewport.h"
24 #include "qgsmaptopixel.h"
25 #include "qgsrendercontext.h"
26 #include <QImage>
27 #include <QPainter>
28 #ifndef QT_NO_PRINTER
29 #include <QPrinter>
30 #endif
31 
32 QgsRasterDrawer::QgsRasterDrawer( QgsRasterIterator *iterator ): mIterator( iterator )
33 {
34 }
35 
36 void QgsRasterDrawer::draw( QPainter *p, QgsRasterViewPort *viewPort, const QgsMapToPixel *qgsMapToPixel, QgsRasterBlockFeedback *feedback )
37 {
38  QgsDebugMsgLevel( QStringLiteral( "Entered" ), 4 );
39  if ( !p || !mIterator || !viewPort || !qgsMapToPixel )
40  {
41  return;
42  }
43 
44  // last pipe filter has only 1 band
45  int bandNumber = 1;
46  mIterator->startRasterRead( bandNumber, viewPort->mWidth, viewPort->mHeight, viewPort->mDrawnExtent, feedback );
47 
48  //number of cols/rows in output pixels
49  int nCols = 0;
50  int nRows = 0;
51  //shift to top left point for the raster part
52  int topLeftCol = 0;
53  int topLeftRow = 0;
54 
55  // We know that the output data type of last pipe filter is QImage data
56 
57  std::unique_ptr< QgsRasterBlock > block;
58 
59  // readNextRasterPart calcs and resets nCols, nRows, topLeftCol, topLeftRow
60  while ( mIterator->readNextRasterPart( bandNumber, nCols, nRows,
61  block, topLeftCol, topLeftRow ) )
62  {
63  if ( !block )
64  {
65  QgsDebugMsg( QStringLiteral( "Cannot get block" ) );
66  continue;
67  }
68 
69  QImage img = block->image();
70 
71 #ifndef QT_NO_PRINTER
72  // Because of bug in Acrobat Reader we must use "white" transparent color instead
73  // of "black" for PDF. See #9101.
74  QPrinter *printer = dynamic_cast<QPrinter *>( p->device() );
75  if ( printer && printer->outputFormat() == QPrinter::PdfFormat )
76  {
77  QgsDebugMsgLevel( QStringLiteral( "PdfFormat" ), 4 );
78 
79  img = img.convertToFormat( QImage::Format_ARGB32 );
80  QRgb transparentBlack = qRgba( 0, 0, 0, 0 );
81  QRgb transparentWhite = qRgba( 255, 255, 255, 0 );
82  for ( int x = 0; x < img.width(); x++ )
83  {
84  for ( int y = 0; y < img.height(); y++ )
85  {
86  if ( img.pixel( x, y ) == transparentBlack )
87  {
88  img.setPixel( x, y, transparentWhite );
89  }
90  }
91  }
92  }
93 #endif
94 
95  if ( feedback && feedback->renderPartialOutput() )
96  {
97  // there could have been partial preview written before
98  // so overwrite anything with the resulting image.
99  // (we are guaranteed to have a temporary image for this layer, see QgsMapRendererJob::needTemporaryImage)
100  p->setCompositionMode( QPainter::CompositionMode_Source );
101  }
102 
103  drawImage( p, viewPort, img, topLeftCol, topLeftRow, qgsMapToPixel );
104 
105  if ( feedback && feedback->renderPartialOutput() )
106  {
107  // go back to the default composition mode
108  p->setCompositionMode( QPainter::CompositionMode_SourceOver );
109  }
110 
111  // OK this does not matter much anyway as the tile size quite big so most of the time
112  // there would be just one tile for the whole display area, but it won't hurt...
113  if ( feedback && feedback->isCanceled() )
114  break;
115  }
116 }
117 
118 void QgsRasterDrawer::drawImage( QPainter *p, QgsRasterViewPort *viewPort, const QImage &img, int topLeftCol, int topLeftRow, const QgsMapToPixel *qgsMapToPixel ) const
119 {
120  if ( !p || !viewPort )
121  {
122  return;
123  }
124 
125  //top left position in device coords
126  QPoint tlPoint = QPoint( viewPort->mTopLeftPoint.x() + topLeftCol, viewPort->mTopLeftPoint.y() + topLeftRow );
127  p->save();
128  p->setRenderHint( QPainter::Antialiasing, false );
129 
130  // Blending problem was reported with PDF output if background color has alpha < 255
131  // in #7766, it seems to be a bug in Qt, setting a brush with alpha 255 is a workaround
132  // which should not harm anything
133  p->setBrush( QBrush( QColor( Qt::white ), Qt::NoBrush ) );
134 
135  if ( qgsMapToPixel )
136  {
137  int w = qgsMapToPixel->mapWidth();
138  int h = qgsMapToPixel->mapHeight();
139 
140  double rotation = qgsMapToPixel->mapRotation();
141  if ( rotation )
142  {
143  // both viewPort and image sizes are dependent on scale
144  double cx = w / 2.0;
145  double cy = h / 2.0;
146  p->translate( cx, cy );
147  p->rotate( rotation );
148  p->translate( -cx, -cy );
149  }
150  }
151 
152  p->drawImage( tlPoint, img );
153 
154 #if 0
155  // For debugging:
156  QRectF br = QRectF( tlPoint, img.size() );
157  QPointF c = br.center();
158  double rad = std::max( br.width(), br.height() ) / 10;
159  p->drawRoundedRect( br, rad, rad );
160  p->drawLine( QLineF( br.x(), br.y(), br.x() + br.width(), br.y() + br.height() ) );
161  p->drawLine( QLineF( br.x() + br.width(), br.y(), br.x(), br.y() + br.height() ) );
162 
163  double nw = br.width() * 0.5;
164  double nh = br.height() * 0.5;
165  br = QRectF( c - QPointF( nw / 2, nh / 2 ), QSize( nw, nh ) );
166  p->drawRoundedRect( br, rad, rad );
167 
168  nw = br.width() * 0.5;
169  nh = br.height() * 0.5;
170  br = QRectF( c - QPointF( nw / 2, nh / 2 ), QSize( nw, nh ) );
171  p->drawRoundedRect( br, rad, rad );
172 #endif
173 
174  p->restore();
175 }
176 
QgsPointXY::y
double y
Definition: qgspointxy.h:48
QgsDebugMsgLevel
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
qgsrasterviewport.h
qgsmaptopixel.h
qgsrasterdrawer.h
QgsRasterViewPort::mTopLeftPoint
QgsPointXY mTopLeftPoint
Coordinate (in output device coordinate system) of top left corner of the part of the raster that is ...
Definition: qgsrasterviewport.h:58
QgsRasterViewPort
Definition: qgsrasterviewport.h:34
QgsDebugMsg
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
qgsrasteriterator.h
qgsrasterinterface.h
QgsRasterDrawer::draw
void draw(QPainter *p, QgsRasterViewPort *viewPort, const QgsMapToPixel *qgsMapToPixel, QgsRasterBlockFeedback *feedback=nullptr)
Draws raster data.
Definition: qgsrasterdrawer.cpp:36
qgsrasterblock.h
QgsMapToPixel::mapHeight
int mapHeight() const
Returns current map height in pixels.
Definition: qgsmaptopixel.cpp:69
QgsMapToPixel::mapRotation
double mapRotation() const
Returns current map rotation in degrees.
Definition: qgsmaptopixel.cpp:158
QgsRasterIterator::startRasterRead
void startRasterRead(int bandNumber, qgssize nCols, qgssize nRows, const QgsRectangle &extent, QgsRasterBlockFeedback *feedback=nullptr)
Start reading of raster band.
Definition: qgsrasteriterator.cpp:38
qgsrendercontext.h
QgsRasterBlockFeedback::renderPartialOutput
bool renderPartialOutput() const
Whether our painter is drawing to a temporary image used just by this layer.
Definition: qgsrasterinterface.h:84
QgsRasterIterator
Definition: qgsrasteriterator.h:34
QgsRasterIterator::readNextRasterPart
bool readNextRasterPart(int bandNumber, int &nCols, int &nRows, QgsRasterBlock **block, int &topLeftCol, int &topLeftRow)
Fetches next part of raster data, caller takes ownership of the block and caller should delete the bl...
Definition: qgsrasteriterator.cpp:65
QgsFeedback::isCanceled
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:66
QgsRasterDrawer::drawImage
void drawImage(QPainter *p, QgsRasterViewPort *viewPort, const QImage &img, int topLeftCol, int topLeftRow, const QgsMapToPixel *mapToPixel=nullptr) const
Draws raster part.
Definition: qgsrasterdrawer.cpp:118
QgsRasterViewPort::mHeight
qgssize mHeight
Distance in map units from bottom edge to top edge for the part of the raster that is to be rendered.
Definition: qgsrasterviewport.h:72
QgsRasterViewPort::mWidth
qgssize mWidth
Width, number of columns to be rendered.
Definition: qgsrasterviewport.h:66
c
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
Definition: porting_processing.dox:1
QgsMapToPixel
Definition: qgsmaptopixel.h:37
QgsMapToPixel::mapWidth
int mapWidth() const
Returns current map width in pixels The information is only known if setRotation was used.
Definition: qgsmaptopixel.cpp:74
QgsRasterDrawer::QgsRasterDrawer
QgsRasterDrawer(QgsRasterIterator *iterator)
Definition: qgsrasterdrawer.cpp:32
QgsPointXY::x
double x
Definition: qgspointxy.h:47
QgsRasterBlockFeedback
Definition: qgsrasterinterface.h:40
qgslogger.h
QgsRasterViewPort::mDrawnExtent
QgsRectangle mDrawnExtent
Intersection of current map extent and layer extent.
Definition: qgsrasterviewport.h:75