QGIS API Documentation  2.8.2-Wien
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups 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  if ( theQgsMapToPixel )
116  {
117  int w = theQgsMapToPixel->mapWidth();
118  int h = theQgsMapToPixel->mapHeight();
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