QGIS API Documentation  3.4.15-Madeira (e83d02e274)
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  mMode = mode;
33  update();
34 }
35 
36 void QgsPreviewEffect::draw( QPainter *painter )
37 {
38  QPoint offset;
39  QPixmap pixmap;
40 
41  if ( sourceIsPixmap() )
42  {
43  // No point in drawing in device coordinates (pixmap will be scaled anyways).
44  pixmap = sourcePixmap( Qt::LogicalCoordinates, &offset );
45  }
46  else
47  {
48  // Draw pixmap in device coordinates to avoid pixmap scaling;
49  pixmap = sourcePixmap( Qt::DeviceCoordinates, &offset );
50  painter->setWorldTransform( QTransform() );
51  }
52 
53  QImage image = pixmap.toImage();
54 
55  switch ( mMode )
56  {
58  {
59  QRgb *line = nullptr;
60 
61  for ( int y = 0; y < image.height(); y++ )
62  {
63  line = ( QRgb * )image.scanLine( y );
64  for ( int x = 0; x < image.width(); x++ )
65  {
66  int gray = 0.21 * qRed( line[x] ) + 0.72 * qGreen( line[x] ) + 0.07 * qBlue( line[x] );
67  line[x] = qRgb( gray, gray, gray );
68  }
69  }
70 
71  painter->drawImage( offset, image );
72  break;
73  }
75  {
76  QImage bwImage = image.convertToFormat( QImage::Format_Mono );
77  painter->drawImage( offset, bwImage );
78  break;
79  }
82  {
83  QRgb *line = nullptr;
84 
85  for ( int y = 0; y < image.height(); y++ )
86  {
87  line = ( QRgb * )image.scanLine( y );
88  for ( int x = 0; x < image.width(); x++ )
89  {
90  line[x] = simulateColorBlindness( line[x], mMode );
91  }
92  }
93 
94  painter->drawImage( offset, image );
95  break;
96  }
97  }
98 
99 }
100 
101 QRgb QgsPreviewEffect::simulateColorBlindness( QRgb &originalColor, QgsPreviewEffect::PreviewMode mode )
102 {
103  int red = qRed( originalColor );
104  int green = qGreen( originalColor );
105  int blue = qBlue( originalColor );
106 
107  //convert RGB to LMS color space
108  // (http://vision.psychol.cam.ac.uk/jdmollon/papers/colourmaps.pdf p245, equation 4) #spellok
109  double L = ( 17.8824 * red ) + ( 43.5161 * green ) + ( 4.11935 * blue );
110  double M = ( 3.45565 * red ) + ( 27.1554 * green ) + ( 3.86714 * blue );
111  double S = ( 0.0299566 * red ) + ( 0.184309 * green ) + ( 1.46709 * blue );
112 
113  //simulate color blindness
114  switch ( mode )
115  {
116  case PreviewProtanope:
117  simulateProtanopeLMS( L, M, S );
118  break;
119  case PreviewDeuteranope:
120  simulateDeuteranopeLMS( L, M, S );
121  break;
122  default:
123  break;
124  }
125 
126  //convert LMS back to RGB color space
127  //(http://vision.psychol.cam.ac.uk/jdmollon/papers/colourmaps.pdf p248, equation 6) #spellok
128  red = ( 0.080944 * L ) + ( -0.130504 * M ) + ( 0.116721 * S );
129  green = ( -0.0102485 * L ) + ( 0.0540194 * M ) + ( -0.113615 * S );
130  blue = ( -0.000365294 * L ) + ( -0.00412163 * M ) + ( 0.693513 * S );
131 
132  //restrict values to 0-255
133  red = std::max( std::min( 255, red ), 0 );
134  green = std::max( std::min( 255, green ), 0 );
135  blue = std::max( std::min( 255, blue ), 0 );
136 
137  return qRgb( red, green, blue );
138 }
139 
140 void QgsPreviewEffect::simulateProtanopeLMS( double &L, double &M, double &S )
141 {
142  //adjust L component to simulate vision of Protanope
143  //(http://vision.psychol.cam.ac.uk/jdmollon/papers/colourmaps.pdf p248, equation 5) #spellok
144  L = ( 2.02344 * M ) + ( -2.52581 * S );
145 }
146 
147 void QgsPreviewEffect::simulateDeuteranopeLMS( double &L, double &M, double &S )
148 {
149  //adjust M component to simulate vision of Deuteranope
150  //(http://vision.psychol.cam.ac.uk/jdmollon/papers/colourmaps.pdf p248, equation 5) #spellok
151  M = ( 0.494207 * L ) + ( 1.24827 * S );
152 }
void setMode(PreviewMode mode)
Sets the mode for the preview effect, which controls how the effect modifies a widgets appearance...
void draw(QPainter *painter) override
PreviewMode mode() const
Returns the mode used for the preview effect.
QgsPreviewEffect(QObject *parent)