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