QGIS API Documentation  2.17.0-Master (872e6d2)
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 "qgsrasterdrawer.h"
20 #include "qgsrasteriterator.h"
21 #include "qgsrasterviewport.h"
22 #include "qgsmaptopixel.h"
23 #include "qgsrendercontext.h"
24 #include <QImage>
25 #include <QPainter>
26 #include <QPrinter>
27 
28 QgsRasterDrawer::QgsRasterDrawer( QgsRasterIterator* iterator ): mIterator( iterator )
29 {
30 }
31 
32 void QgsRasterDrawer::draw( QPainter* p, QgsRasterViewPort* viewPort, const QgsMapToPixel* theQgsMapToPixel, const QgsRenderContext* ctx )
33 {
34  QgsDebugMsgLevel( "Entered", 4 );
35  if ( !p || !mIterator || !viewPort || !theQgsMapToPixel )
36  {
37  return;
38  }
39 
40  // last pipe filter has only 1 band
41  int bandNumber = 1;
42  mIterator->startRasterRead( bandNumber, viewPort->mWidth, viewPort->mHeight, viewPort->mDrawnExtent );
43 
44  //number of cols/rows in output pixels
45  int nCols = 0;
46  int nRows = 0;
47  //shift to top left point for the raster part
48  int topLeftCol = 0;
49  int topLeftRow = 0;
50 
51  // We know that the output data type of last pipe filter is QImage data
52 
53  QgsRasterBlock *block;
54 
55  // readNextRasterPart calcs and resets nCols, nRows, topLeftCol, topLeftRow
56  while ( mIterator->readNextRasterPart( bandNumber, nCols, nRows,
57  &block, topLeftCol, topLeftRow ) )
58  {
59  if ( !block )
60  {
61  QgsDebugMsg( "Cannot get block" );
62  continue;
63  }
64 
65  QImage img = block->image();
66 
67  // Because of bug in Acrobat Reader we must use "white" transparent color instead
68  // of "black" for PDF. See #9101.
69  QPrinter *printer = dynamic_cast<QPrinter *>( p->device() );
70  if ( printer && printer->outputFormat() == QPrinter::PdfFormat )
71  {
72  QgsDebugMsgLevel( "PdfFormat", 4 );
73 
74  img = img.convertToFormat( QImage::Format_ARGB32 );
75  QRgb transparentBlack = qRgba( 0, 0, 0, 0 );
76  QRgb transparentWhite = qRgba( 255, 255, 255, 0 );
77  for ( int x = 0; x < img.width(); x++ )
78  {
79  for ( int y = 0; y < img.height(); y++ )
80  {
81  if ( img.pixel( x, y ) == transparentBlack )
82  {
83  img.setPixel( x, y, transparentWhite );
84  }
85  }
86  }
87  }
88 
89  drawImage( p, viewPort, img, topLeftCol, topLeftRow, theQgsMapToPixel );
90 
91  delete block;
92  if ( ctx && ctx->renderingStopped() )
93  break;
94  }
95 }
96 
97 void QgsRasterDrawer::drawImage( QPainter* p, QgsRasterViewPort* viewPort, const QImage& img, int topLeftCol, int topLeftRow, const QgsMapToPixel* theQgsMapToPixel ) const
98 {
99  if ( !p || !viewPort )
100  {
101  return;
102  }
103 
104  //top left position in device coords
105  QPoint tlPoint = QPoint( viewPort->mTopLeftPoint.x() + topLeftCol, viewPort->mTopLeftPoint.y() + topLeftRow );
106  p->save();
107  p->setRenderHint( QPainter::Antialiasing, false );
108 
109  // Blending problem was reported with PDF output if background color has alpha < 255
110  // in #7766, it seems to be a bug in Qt, setting a brush with alpha 255 is a workaround
111  // which should not harm anything
112  p->setBrush( QBrush( QColor( Qt::white ), Qt::NoBrush ) );
113 
114  if ( theQgsMapToPixel )
115  {
116  int w = theQgsMapToPixel->mapWidth();
117  int h = theQgsMapToPixel->mapHeight();
118 
119  double rotation = theQgsMapToPixel->mapRotation();
120  if ( rotation )
121  {
122  // both viewPort and image sizes are dependent on scale
123  double cx = w / 2.0;
124  double cy = h / 2.0;
125  p->translate( cx, cy );
126  p->rotate( rotation );
127  p->translate( -cx, -cy );
128  }
129  }
130 
131  p->drawImage( tlPoint, img );
132 
133 #if 0
134  // For debugging:
135  QRectF br = QRectF( tlPoint, img.size() );
136  QPointF c = br.center();
137  double rad = std::max( br.width(), br.height() ) / 10;
138  p->drawRoundedRect( br, rad, rad );
139  p->drawLine( QLineF( br.x(), br.y(), br.x() + br.width(), br.y() + br.height() ) );
140  p->drawLine( QLineF( br.x() + br.width(), br.y(), br.x(), br.y() + br.height() ) );
141 
142  double nw = br.width() * 0.5;
143  double nh = br.height() * 0.5;
144  br = QRectF( c - QPointF( nw / 2, nh / 2 ), QSize( nw, nh ) );
145  p->drawRoundedRect( br, rad, rad );
146 
147  nw = br.width() * 0.5;
148  nh = br.height() * 0.5;
149  br = QRectF( c - QPointF( nw / 2, nh / 2 ), QSize( nw, nh ) );
150  p->drawRoundedRect( br, rad, rad );
151 #endif
152 
153  p->restore();
154 }
155 
int mapWidth() const
Return current map width in pixels The information is only known if setRotation was used...
QImage convertToFormat(Format format, QFlags< Qt::ImageConversionFlag > flags) const
Iterator for sequentially processing raster cells.
void setRenderHint(RenderHint hint, bool on)
void startRasterRead(int bandNumber, int nCols, int nRows, const QgsRectangle &extent)
Start reading of raster band.
qreal x() const
qreal y() const
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
void setPixel(int x, int y, uint index_or_rgb)
int mWidth
Width, number of columns to be rendered.
void save()
void rotate(qreal angle)
void drawLine(const QLineF &line)
double mapRotation() const
Return current map rotation in degrees.
double x() const
Get the x value of the point.
Definition: qgspoint.h:185
double ANALYSIS_EXPORT max(double x, double y)
Returns the maximum of two doubles or the first argument if both are equal.
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:34
QRgb pixel(int x, int y) const
Raster data container.
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:34
bool renderingStopped() const
int width() const
void drawRoundedRect(const QRectF &rect, qreal xRadius, qreal yRadius, Qt::SizeMode mode)
QPaintDevice * device() const
QgsRasterDrawer(QgsRasterIterator *iterator)
void setBrush(const QBrush &brush)
QPointF center() const
void drawImage(QPainter *p, QgsRasterViewPort *viewPort, const QImage &img, int topLeftCol, int topLeftRow, const QgsMapToPixel *mapToPixel=nullptr) const
Draws raster part.
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...
void restore()
Contains information about the context of a rendering operation.
void drawImage(const QRectF &target, const QImage &image, const QRectF &source, QFlags< Qt::ImageConversionFlag > flags)
qreal width() const
int mHeight
Distance in map units from bottom edge to top edge for the part of the raster that is to be rendered...
QSize size() const
void translate(const QPointF &offset)
int mapHeight() const
Return current map height in pixels.
OutputFormat outputFormat() const
double y() const
Get the y value of the point.
Definition: qgspoint.h:193
QImage image() const
Get image if type is color.
qreal height() const
int height() const
void draw(QPainter *p, QgsRasterViewPort *viewPort, const QgsMapToPixel *theQgsMapToPixel, const QgsRenderContext *ctx=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.
QgsRectangle mDrawnExtent
Intersection of current map extent and layer extent.