QGIS API Documentation  3.23.0-Master (22c16f2067)
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  const QImage bwImage = image.convertToFormat( QImage::Format_Mono );
60  painter->drawImage( offset, bwImage );
61  break;
62  }
67  {
68  QRgb *line = nullptr;
69 
70  for ( int y = 0; y < image.height(); y++ )
71  {
72  line = ( QRgb * )image.scanLine( y );
73  for ( int x = 0; x < image.width(); x++ )
74  {
75  line[x] = simulateColorBlindness( line[x], mMode );
76  }
77  }
78 
79  painter->drawImage( offset, image );
80  break;
81  }
82  }
83 
84 }
85 
86 QRgb QgsPreviewEffect::simulateColorBlindness( QRgb &originalColor, QgsPreviewEffect::PreviewMode mode )
87 {
88  int red = qRed( originalColor );
89  int green = qGreen( originalColor );
90  int blue = qBlue( originalColor );
91 
92  int r = red;
93  int g = green;
94  int b = blue;
95 
96  //simulate color blindness
97  //matrix values taken from Machado et al. (2009), https://doi.org/10.1109/TVCG.2009.113:
98  //https://www.inf.ufrgs.br/~oliveira/pubs_files/CVD_Simulation/CVD_Simulation.html
99  switch ( mode )
100  {
101  case PreviewGrayscale:
102  simulateGrayscale( r, g, b, red, green, blue );
103  break;
104  case PreviewProtanope:
105  simulateProtanope( r, g, b, red, green, blue );
106  break;
107  case PreviewDeuteranope:
108  simulateDeuteranope( r, g, b, red, green, blue );
109  break;
110  case PreviewTritanope:
111  simulateTritanope( r, g, b, red, green, blue );
112  break;
113  default:
114  break;
115  }
116 
117  //restrict values to 0-255
118  r = std::max( std::min( 255, r ), 0 );
119  g = std::max( std::min( 255, g ), 0 );
120  b = std::max( std::min( 255, b ), 0 );
121 
122  return qRgb( r, g, b );
123 }
124 
125 void QgsPreviewEffect::simulateGrayscale( int &r, int &g, int &b, int &red, int &green, int &blue )
126 {
127  r = ( 0.2126 * red ) + ( 0.7152 * green ) + ( 0.0722 * blue );
128  g = r;
129  b = r;
130 }
131 
132 void QgsPreviewEffect::simulateProtanope( int &r, int &g, int &b, int &red, int &green, int &blue )
133 {
134  r = ( 0.152286 * red ) + ( 1.052583 * green ) + ( -0.204868 * blue );
135  g = ( 0.114503 * red ) + ( 0.786281 * green ) + ( 0.099216 * blue );
136  b = ( -0.003882 * red ) + ( -0.048116 * green ) + ( 1.051998 * blue );
137 }
138 
139 void QgsPreviewEffect::simulateDeuteranope( int &r, int &g, int &b, int &red, int &green, int &blue )
140 {
141  r = ( 0.367322 * red ) + ( 0.860646 * green ) + ( -0.227968 * blue );
142  g = ( 0.280085 * red ) + ( 0.672501 * green ) + ( 0.047413 * blue );
143  b = ( -0.011820 * red ) + ( 0.042940 * green ) + ( 0.968881 * blue );
144 }
145 
146 void QgsPreviewEffect::simulateTritanope( int &r, int &g, int &b, int &red, int &green, int &blue )
147 {
148  r = ( 1.255528 * red ) + ( -0.076749 * green ) + ( -0.178779 * blue );
149  g = ( -0.078411 * red ) + ( 0.930809 * green ) + ( 0.147602 * blue );
150  b = ( 0.004733 * red ) + ( 0.691367 * green ) + ( 0.303900 * blue );
151 }
void draw(QPainter *painter) override
void setMode(PreviewMode mode)
Sets the mode for the preview effect, which controls how the effect modifies a widgets appearance.
PreviewMode mode() const
Returns the mode used for the preview effect.
QgsPreviewEffect(QObject *parent)