QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
qgsprevieweffect.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsprevieweffect.cpp
3  -------------------
4  begin : March 2014
5  copyright : (C) 2014 by Nyall Dawson
6  email : nyall dot dawson at gmail dot 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 <QPainter>
19 #include "qgsprevieweffect.h"
20 
21 
23  : QGraphicsEffect( parent )
24  , mMode( PreviewGrayscale )
25 {
26  //effect is disabled by default
27  setEnabled( false );
28 }
29 
31 {
32 
33 }
34 
36 {
37  mMode = mode;
38  update();
39 }
40 
42 {
43  QPoint offset;
44  QPixmap pixmap;
45 
46  if ( sourceIsPixmap() )
47  {
48  // No point in drawing in device coordinates (pixmap will be scaled anyways).
49  pixmap = sourcePixmap( Qt::LogicalCoordinates, &offset );
50  }
51  else
52  {
53  // Draw pixmap in device coordinates to avoid pixmap scaling;
54  pixmap = sourcePixmap( Qt::DeviceCoordinates, &offset );
55  painter->setWorldTransform( QTransform() );
56  }
57 
58  QImage image = pixmap.toImage();
59 
60  switch ( mMode )
61  {
63  {
64  QRgb * line;
65 
66  for ( int y = 0; y < image.height(); y++ )
67  {
68  line = ( QRgb * )image.scanLine( y );
69  for ( int x = 0; x < image.width(); x++ )
70  {
71  int gray = 0.21 * qRed( line[x] ) + 0.72 * qGreen( line[x] ) + 0.07 * qBlue( line[x] );
72  line[x] = qRgb( gray, gray, gray );
73  }
74  }
75 
76  painter->drawImage( offset, image );
77  break;
78  }
80  {
81  QImage bwImage = image.convertToFormat( QImage::Format_Mono );
82  painter->drawImage( offset, bwImage );
83  break;
84  }
87  {
88  QRgb * line;
89 
90  for ( int y = 0; y < image.height(); y++ )
91  {
92  line = ( QRgb * )image.scanLine( y );
93  for ( int x = 0; x < image.width(); x++ )
94  {
95  line[x] = simulateColorBlindness( line[x], mMode );
96  }
97  }
98 
99  painter->drawImage( offset, image );
100  break;
101  }
102  }
103 
104 }
105 
106 QRgb QgsPreviewEffect::simulateColorBlindness( QRgb& originalColor, QgsPreviewEffect::PreviewMode mode )
107 {
108  int red = qRed( originalColor );
109  int green = qGreen( originalColor );
110  int blue = qBlue( originalColor );
111 
112  //convert RGB to LMS color space
113  // (http://vision.psychol.cam.ac.uk/jdmollon/papers/colourmaps.pdf p245, equation 4)
114  double L = ( 17.8824 * red ) + ( 43.5161 * green ) + ( 4.11935 * blue );
115  double M = ( 3.45565 * red ) + ( 27.1554 * green ) + ( 3.86714 * blue );
116  double S = ( 0.0299566 * red ) + ( 0.184309 * green ) + ( 1.46709 * blue );
117 
118  //simulate color blindness
119  switch ( mode )
120  {
121  case PreviewProtanope:
122  simulateProtanopeLMS( L, M, S );
123  break;
124  case PreviewDeuteranope:
125  simulateDeuteranopeLMS( L, M, S );
126  break;
127  default:
128  break;
129  }
130 
131  //convert LMS back to RGB color space
132  //(http://vision.psychol.cam.ac.uk/jdmollon/papers/colourmaps.pdf p248, equation 6)
133  red = ( 0.080944 * L ) + ( -0.130504 * M ) + ( 0.116721 * S );
134  green = ( -0.0102485 * L ) + ( 0.0540194 * M ) + ( -0.113615 * S );
135  blue = ( -0.000365294 * L ) + ( -0.00412163 * M ) + ( 0.693513 * S );
136 
137  //restrict values to 0-255
138  red = qMax( qMin( 255, red ), 0 );
139  green = qMax( qMin( 255, green ), 0 );
140  blue = qMax( qMin( 255, blue ), 0 );
141 
142  return qRgb( red, green, blue );
143 }
144 
145 void QgsPreviewEffect::simulateProtanopeLMS( double& L, double &M, double &S )
146 {
147  //adjust L component to simulate vision of Protanope
148  //(http://vision.psychol.cam.ac.uk/jdmollon/papers/colourmaps.pdf p248, equation 5)
149  L = ( 2.02344 * M ) + ( -2.52581 * S );
150 }
151 
152 void QgsPreviewEffect::simulateDeuteranopeLMS( double& L, double &M, double &S )
153 {
154  //adjust M component to simulate vision of Deuteranope
155  //(http://vision.psychol.cam.ac.uk/jdmollon/papers/colourmaps.pdf p248, equation 5)
156  M = ( 0.494207 * L ) + ( 1.24827 * S );
157 }
uchar * scanLine(int i)
QImage convertToFormat(Format format, QFlags< Qt::ImageConversionFlag > flags) const
void setEnabled(bool enable)
QPixmap sourcePixmap(Qt::CoordinateSystem system, QPoint *offset, PixmapPadMode mode) const
void setWorldTransform(const QTransform &matrix, bool combine)
int width() const
void setMode(PreviewMode mode)
Sets the mode for the preview effect, which controls how the effect modifies a widgets appearance...
bool sourceIsPixmap() const
PreviewMode mode() const
Returns the mode used for the preview effect.
void drawImage(const QRectF &target, const QImage &image, const QRectF &source, QFlags< Qt::ImageConversionFlag > flags)
virtual void draw(QPainter *painter) override
int height() const
QImage toImage() const
QgsPreviewEffect(QObject *parent)