mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-03 00:05:24 -04:00
153 lines
4.8 KiB
C++
153 lines
4.8 KiB
C++
/***************************************************************************
|
|
qgsprevieweffect.cpp
|
|
-------------------
|
|
begin : March 2014
|
|
copyright : (C) 2014 by Nyall Dawson
|
|
email : nyall dot dawson at gmail dot com
|
|
***************************************************************************/
|
|
|
|
/***************************************************************************
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#include <QPainter>
|
|
#include "qgsprevieweffect.h"
|
|
|
|
|
|
QgsPreviewEffect::QgsPreviewEffect( QObject *parent )
|
|
: QGraphicsEffect( parent )
|
|
, mMode( PreviewGrayscale )
|
|
{
|
|
//effect is disabled by default
|
|
setEnabled( false );
|
|
}
|
|
|
|
void QgsPreviewEffect::setMode( QgsPreviewEffect::PreviewMode mode )
|
|
{
|
|
mMode = mode;
|
|
update();
|
|
}
|
|
|
|
void QgsPreviewEffect::draw( QPainter *painter )
|
|
{
|
|
QPoint offset;
|
|
QPixmap pixmap;
|
|
|
|
if ( sourceIsPixmap() )
|
|
{
|
|
// No point in drawing in device coordinates (pixmap will be scaled anyways).
|
|
pixmap = sourcePixmap( Qt::LogicalCoordinates, &offset );
|
|
}
|
|
else
|
|
{
|
|
// Draw pixmap in device coordinates to avoid pixmap scaling;
|
|
pixmap = sourcePixmap( Qt::DeviceCoordinates, &offset );
|
|
painter->setWorldTransform( QTransform() );
|
|
}
|
|
|
|
QImage image = pixmap.toImage();
|
|
|
|
switch ( mMode )
|
|
{
|
|
case QgsPreviewEffect::PreviewGrayscale:
|
|
{
|
|
QRgb *line = nullptr;
|
|
|
|
for ( int y = 0; y < image.height(); y++ )
|
|
{
|
|
line = ( QRgb * )image.scanLine( y );
|
|
for ( int x = 0; x < image.width(); x++ )
|
|
{
|
|
int gray = 0.21 * qRed( line[x] ) + 0.72 * qGreen( line[x] ) + 0.07 * qBlue( line[x] );
|
|
line[x] = qRgb( gray, gray, gray );
|
|
}
|
|
}
|
|
|
|
painter->drawImage( offset, image );
|
|
break;
|
|
}
|
|
case QgsPreviewEffect::PreviewMono:
|
|
{
|
|
QImage bwImage = image.convertToFormat( QImage::Format_Mono );
|
|
painter->drawImage( offset, bwImage );
|
|
break;
|
|
}
|
|
case QgsPreviewEffect::PreviewProtanope:
|
|
case QgsPreviewEffect::PreviewDeuteranope:
|
|
{
|
|
QRgb *line = nullptr;
|
|
|
|
for ( int y = 0; y < image.height(); y++ )
|
|
{
|
|
line = ( QRgb * )image.scanLine( y );
|
|
for ( int x = 0; x < image.width(); x++ )
|
|
{
|
|
line[x] = simulateColorBlindness( line[x], mMode );
|
|
}
|
|
}
|
|
|
|
painter->drawImage( offset, image );
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
QRgb QgsPreviewEffect::simulateColorBlindness( QRgb &originalColor, QgsPreviewEffect::PreviewMode mode )
|
|
{
|
|
int red = qRed( originalColor );
|
|
int green = qGreen( originalColor );
|
|
int blue = qBlue( originalColor );
|
|
|
|
//convert RGB to LMS color space
|
|
// (http://vision.psychol.cam.ac.uk/jdmollon/papers/colourmaps.pdf p245, equation 4) #spellok
|
|
double L = ( 17.8824 * red ) + ( 43.5161 * green ) + ( 4.11935 * blue );
|
|
double M = ( 3.45565 * red ) + ( 27.1554 * green ) + ( 3.86714 * blue );
|
|
double S = ( 0.0299566 * red ) + ( 0.184309 * green ) + ( 1.46709 * blue );
|
|
|
|
//simulate color blindness
|
|
switch ( mode )
|
|
{
|
|
case PreviewProtanope:
|
|
simulateProtanopeLMS( L, M, S );
|
|
break;
|
|
case PreviewDeuteranope:
|
|
simulateDeuteranopeLMS( L, M, S );
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
//convert LMS back to RGB color space
|
|
//(http://vision.psychol.cam.ac.uk/jdmollon/papers/colourmaps.pdf p248, equation 6) #spellok
|
|
red = ( 0.080944 * L ) + ( -0.130504 * M ) + ( 0.116721 * S );
|
|
green = ( -0.0102485 * L ) + ( 0.0540194 * M ) + ( -0.113615 * S );
|
|
blue = ( -0.000365294 * L ) + ( -0.00412163 * M ) + ( 0.693513 * S );
|
|
|
|
//restrict values to 0-255
|
|
red = std::max( std::min( 255, red ), 0 );
|
|
green = std::max( std::min( 255, green ), 0 );
|
|
blue = std::max( std::min( 255, blue ), 0 );
|
|
|
|
return qRgb( red, green, blue );
|
|
}
|
|
|
|
void QgsPreviewEffect::simulateProtanopeLMS( double &L, double &M, double &S )
|
|
{
|
|
//adjust L component to simulate vision of Protanope
|
|
//(http://vision.psychol.cam.ac.uk/jdmollon/papers/colourmaps.pdf p248, equation 5) #spellok
|
|
L = ( 2.02344 * M ) + ( -2.52581 * S );
|
|
}
|
|
|
|
void QgsPreviewEffect::simulateDeuteranopeLMS( double &L, double &M, double &S )
|
|
{
|
|
//adjust M component to simulate vision of Deuteranope
|
|
//(http://vision.psychol.cam.ac.uk/jdmollon/papers/colourmaps.pdf p248, equation 5) #spellok
|
|
M = ( 0.494207 * L ) + ( 1.24827 * S );
|
|
}
|