QGIS API Documentation  3.10.0-A Coruña (6c816b4204)
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 
void drawImage(QPainter *p, QgsRasterViewPort *viewPort, const QImage &img, int topLeftCol, int topLeftRow, const QgsMapToPixel *mapToPixel=nullptr) const
Draws raster part.
bool renderPartialOutput() const
Whether our painter is drawing to a temporary image used just by this layer.
Iterator for sequentially processing raster cells.
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
double y
Definition: qgspointxy.h:48
int mWidth
Width, number of columns to be rendered.
double mapRotation() const
Returns current map rotation in degrees.
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
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:37
int mapWidth() const
Returns current map width in pixels The information is only known if setRotation was used...
int mapHeight() const
Returns current map height in pixels.
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
QgsRasterDrawer(QgsRasterIterator *iterator)
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...
double x
Definition: qgspointxy.h:47
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:54
int mHeight
Distance in map units from bottom edge to top edge for the part of the raster that is to be rendered...
This class provides details of the viewable area that a raster will be rendered into.
Feedback object tailored for raster block reading.
void draw(QPainter *p, QgsRasterViewPort *viewPort, const QgsMapToPixel *qgsMapToPixel, QgsRasterBlockFeedback *feedback=nullptr)
Draws raster data.
void startRasterRead(int bandNumber, int nCols, int nRows, const QgsRectangle &extent, QgsRasterBlockFeedback *feedback=nullptr)
Start reading of raster band.
QgsRectangle mDrawnExtent
Intersection of current map extent and layer extent.
QgsPointXY mTopLeftPoint
Coordinate (in output device coordinate system) of top left corner of the part of the raster that is ...