QGIS API Documentation  2.99.0-Master (e077efd)
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 #include <QPrinter>
29 
30 QgsRasterDrawer::QgsRasterDrawer( QgsRasterIterator* iterator ): mIterator( iterator )
31 {
32 }
33 
34 void QgsRasterDrawer::draw( QPainter* p, QgsRasterViewPort* viewPort, const QgsMapToPixel* theQgsMapToPixel, QgsRasterBlockFeedback* feedback )
35 {
36  QgsDebugMsgLevel( "Entered", 4 );
37  if ( !p || !mIterator || !viewPort || !theQgsMapToPixel )
38  {
39  return;
40  }
41 
42  // last pipe filter has only 1 band
43  int bandNumber = 1;
44  mIterator->startRasterRead( bandNumber, viewPort->mWidth, viewPort->mHeight, viewPort->mDrawnExtent, feedback );
45 
46  //number of cols/rows in output pixels
47  int nCols = 0;
48  int nRows = 0;
49  //shift to top left point for the raster part
50  int topLeftCol = 0;
51  int topLeftRow = 0;
52 
53  // We know that the output data type of last pipe filter is QImage data
54 
55  QgsRasterBlock *block;
56 
57  // readNextRasterPart calcs and resets nCols, nRows, topLeftCol, topLeftRow
58  while ( mIterator->readNextRasterPart( bandNumber, nCols, nRows,
59  &block, topLeftCol, topLeftRow ) )
60  {
61  if ( !block )
62  {
63  QgsDebugMsg( "Cannot get block" );
64  continue;
65  }
66 
67  QImage img = block->image();
68 
69  // Because of bug in Acrobat Reader we must use "white" transparent color instead
70  // of "black" for PDF. See #9101.
71  QPrinter *printer = dynamic_cast<QPrinter *>( p->device() );
72  if ( printer && printer->outputFormat() == QPrinter::PdfFormat )
73  {
74  QgsDebugMsgLevel( "PdfFormat", 4 );
75 
76  img = img.convertToFormat( QImage::Format_ARGB32 );
77  QRgb transparentBlack = qRgba( 0, 0, 0, 0 );
78  QRgb transparentWhite = qRgba( 255, 255, 255, 0 );
79  for ( int x = 0; x < img.width(); x++ )
80  {
81  for ( int y = 0; y < img.height(); y++ )
82  {
83  if ( img.pixel( x, y ) == transparentBlack )
84  {
85  img.setPixel( x, y, transparentWhite );
86  }
87  }
88  }
89  }
90 
91  if ( feedback && feedback->renderPartialOutput() )
92  {
93  // there could have been partial preview written before
94  // so overwrite anything with the resulting image.
95  // (we are guaranteed to have a temporary image for this layer, see QgsMapRendererJob::needTemporaryImage)
96  p->setCompositionMode( QPainter::CompositionMode_Source );
97  }
98 
99  drawImage( p, viewPort, img, topLeftCol, topLeftRow, theQgsMapToPixel );
100 
101  delete block;
102 
103  p->setCompositionMode( QPainter::CompositionMode_SourceOver ); // go back to the default composition mode
104 
105  // ok this does not matter much anyway as the tile size quite big so most of the time
106  // there would be just one tile for the whole display area, but it won't hurt...
107  if ( feedback && feedback->isCancelled() )
108  break;
109  }
110 }
111 
112 void QgsRasterDrawer::drawImage( QPainter* p, QgsRasterViewPort* viewPort, const QImage& img, int topLeftCol, int topLeftRow, const QgsMapToPixel* theQgsMapToPixel ) const
113 {
114  if ( !p || !viewPort )
115  {
116  return;
117  }
118 
119  //top left position in device coords
120  QPoint tlPoint = QPoint( viewPort->mTopLeftPoint.x() + topLeftCol, viewPort->mTopLeftPoint.y() + topLeftRow );
121  p->save();
122  p->setRenderHint( QPainter::Antialiasing, false );
123 
124  // Blending problem was reported with PDF output if background color has alpha < 255
125  // in #7766, it seems to be a bug in Qt, setting a brush with alpha 255 is a workaround
126  // which should not harm anything
127  p->setBrush( QBrush( QColor( Qt::white ), Qt::NoBrush ) );
128 
129  if ( theQgsMapToPixel )
130  {
131  int w = theQgsMapToPixel->mapWidth();
132  int h = theQgsMapToPixel->mapHeight();
133 
134  double rotation = theQgsMapToPixel->mapRotation();
135  if ( rotation )
136  {
137  // both viewPort and image sizes are dependent on scale
138  double cx = w / 2.0;
139  double cy = h / 2.0;
140  p->translate( cx, cy );
141  p->rotate( rotation );
142  p->translate( -cx, -cy );
143  }
144  }
145 
146  p->drawImage( tlPoint, img );
147 
148 #if 0
149  // For debugging:
150  QRectF br = QRectF( tlPoint, img.size() );
151  QPointF c = br.center();
152  double rad = std::max( br.width(), br.height() ) / 10;
153  p->drawRoundedRect( br, rad, rad );
154  p->drawLine( QLineF( br.x(), br.y(), br.x() + br.width(), br.y() + br.height() ) );
155  p->drawLine( QLineF( br.x() + br.width(), br.y(), br.x(), br.y() + br.height() ) );
156 
157  double nw = br.width() * 0.5;
158  double nh = br.height() * 0.5;
159  br = QRectF( c - QPointF( nw / 2, nh / 2 ), QSize( nw, nh ) );
160  p->drawRoundedRect( br, rad, rad );
161 
162  nw = br.width() * 0.5;
163  nh = br.height() * 0.5;
164  br = QRectF( c - QPointF( nw / 2, nh / 2 ), QSize( nw, nh ) );
165  p->drawRoundedRect( br, rad, rad );
166 #endif
167 
168  p->restore();
169 }
170 
void drawImage(QPainter *p, QgsRasterViewPort *viewPort, const QImage &img, int topLeftCol, int topLeftRow, const QgsMapToPixel *mapToPixel=nullptr) const
Draws raster part.
double y
Definition: qgspoint.h:116
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:33
int mWidth
Width, number of columns to be rendered.
bool isCancelled() const
Tells whether the operation has been cancelled already.
Definition: qgsfeedback.h:62
double mapRotation() const
Return current map rotation in degrees.
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:33
int mapWidth() const
Return current map width in pixels The information is only known if setRotation was used...
int mapHeight() const
Return current map height in pixels.
Raster data container.
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:34
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 ANALYSIS_EXPORT max(double x, double y)
Returns the maximum of two doubles or the first argument if both are equal.
Definition: MathUtils.cc:437
QImage image() const
Get image if type is color.
int mHeight
Distance in map units from bottom edge to top edge for the part of the raster that is to be rendered...
void draw(QPainter *p, QgsRasterViewPort *viewPort, const QgsMapToPixel *theQgsMapToPixel, QgsRasterBlockFeedback *feedback=nullptr)
Draws raster data.
QgsPoint mTopLeftPoint
Coordinate (in output device coordinate system) of top left corner of the part of the raster that is ...
This class provides details of the viewable area that a raster will be rendered into.
Feedback object tailored for raster block reading.
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.
double x
Definition: qgspoint.h:115