2
For general Scribus (>=1.3.2) copyright and licensing information please refer
3
to the COPYING file provided with the program. Following this notice may exist
4
a copyright and/or license notice that predates the release of Scribus 1.3.2
5
for which a new license (GPL+exception) is in place.
7
#include "colorblind.h"
8
//#include "colorblind.moc"
12
//#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
15
VisionDefectColor::VisionDefectColor(int r, int g, int b)
20
originalColor = QColor(r, g, b);
24
VisionDefectColor::VisionDefectColor(QColor c)
26
red = (double)c.red();
27
green = (double)c.green();
28
blue = (double)c.blue();
33
VisionDefectColor::VisionDefectColor()
38
originalColor = QColor(0, 0, 0);
42
void VisionDefectColor::init()
44
rgb2lms[0] = 0.05059983;
45
rgb2lms[1] = 0.08585369;
46
rgb2lms[2] = 0.00952420;
48
rgb2lms[3] = 0.01893033;
49
rgb2lms[4] = 0.08925308;
50
rgb2lms[5] = 0.01370054;
52
rgb2lms[6] = 0.00292202;
53
rgb2lms[7] = 0.00975732;
54
rgb2lms[8] = 0.07145979;
56
lms2rgb[0] = 30.830854;
57
lms2rgb[1] = -29.832659;
58
lms2rgb[2] = 1.610474;
60
lms2rgb[3] = -6.481468;
61
lms2rgb[4] = 17.715578;
62
lms2rgb[5] = -2.532642;
64
lms2rgb[6] = -0.375690;
65
lms2rgb[7] = -1.199062;
66
lms2rgb[8] = 14.273846;
73
void VisionDefectColor::convertDefect()
77
/* Remove gamma to linearize RGB intensities */
78
red = pow(red, 1.0 / gammaRGB[0]);
79
green = pow(green, 1.0 / gammaRGB[1]);
80
blue = pow(blue, 1.0 / gammaRGB[2]);
82
/* Convert to LMS (dot product with transform matrix) */
84
double greenOld = green;
86
red = redOld * rgb2lms[0] + greenOld * rgb2lms[1] + blue * rgb2lms[2];
87
green = redOld * rgb2lms[3] + greenOld * rgb2lms[4] + blue * rgb2lms[5];
88
blue = redOld * rgb2lms[6] + greenOld * rgb2lms[7] + blue * rgb2lms[8];
94
case deuteranopeVision:
97
/* See which side of the inflection line we fall... */
99
green = -(a1 * red + c1 * blue) / b1;
101
green = -(a2 * red + c2 * blue) / b2;
103
case protanopeVision:
106
/* See which side of the inflection line we fall... */
107
if (tmp < inflection)
108
red = -(b1 * green + c1 * blue) / a1;
110
red = -(b2 * green + c2 * blue) / a2;
112
case tritanopeVision:
115
/* See which side of the inflection line we fall... */
116
if (tmp < inflection)
117
blue = -(a1 * red + b1 * green) / c1;
119
blue = -(a2 * red + b2 * green) / c2;
121
case colorBlindnessVision:
123
double gray = clamp(0.3 * originalColor.red()
124
+ 0.59 * originalColor.green()
125
+ 0.11 * originalColor.blue(), 0, 255);
129
return; // no other transformations!
135
/* Convert back to RGB (cross product with transform matrix) */
139
red = redOld * lms2rgb[0] + greenOld * lms2rgb[1] + blue * lms2rgb[2];
140
green = redOld * lms2rgb[3] + greenOld * lms2rgb[4] + blue * lms2rgb[5];
141
blue = redOld * lms2rgb[6] + greenOld * lms2rgb[7] + blue * lms2rgb[8];
143
/* Apply gamma to go back to non-linear intensities */
144
red = pow(red, gammaRGB[0]);
145
green = pow(green, gammaRGB[1]);
146
blue = pow(blue, gammaRGB[2]);
148
/* Ensure that we stay within the RGB gamut */
149
/* *** FIX THIS: it would be better to desaturate than blindly clip. */
150
red = clamp(red, 0.0, 255.0);
151
green = clamp(green, 0.0, 255.0);
152
blue = clamp(blue, 0.0, 255.0);
155
QColor VisionDefectColor::convertDefect(QColor c, int d)
157
red = (double)c.red();
158
green = (double)c.green();
159
blue = (double)c.blue();
167
void VisionDefectColor::setupDefect()
173
Load the LMS anchor-point values for lambda = 475 & 485 nm (for
174
protans & deutans) and the LMS values for lambda = 575 & 660 nm
177
anchor[0] = 0.08008; anchor[1] = 0.1579; anchor[2] = 0.5897;
178
anchor[3] = 0.1284; anchor[4] = 0.2237; anchor[5] = 0.3636;
179
anchor[6] = 0.9856; anchor[7] = 0.7325; anchor[8] = 0.001079;
180
anchor[9] = 0.0914; anchor[10] = 0.007009; anchor[11] = 0.0;
182
/* We also need LMS for RGB=(1,1,1)- the equal-energy point (one of
183
* our anchors) (we can just peel this out of the rgb2lms transform
186
anchor_e[0] = rgb2lms[0] + rgb2lms[1] + rgb2lms[2];
187
anchor_e[1] = rgb2lms[3] + rgb2lms[4] + rgb2lms[5];
188
anchor_e[2] = rgb2lms[6] + rgb2lms[7] + rgb2lms[8];
192
case deuteranopeVision:
193
/* find a,b,c for lam=575nm and lam=475 */
194
a1 = anchor_e[1] * anchor[8] - anchor_e[2] * anchor[7];
195
b1 = anchor_e[2] * anchor[6] - anchor_e[0] * anchor[8];
196
c1 = anchor_e[0] * anchor[7] - anchor_e[1] * anchor[6];
197
a2 = anchor_e[1] * anchor[2] - anchor_e[2] * anchor[1];
198
b2 = anchor_e[2] * anchor[0] - anchor_e[0] * anchor[2];
199
c2 = anchor_e[0] * anchor[1] - anchor_e[1] * anchor[0];
200
inflection = (anchor_e[2] / anchor_e[0]);
202
case protanopeVision:
203
/* find a,b,c for lam=575nm and lam=475 */
204
a1 = anchor_e[1] * anchor[8] - anchor_e[2] * anchor[7];
205
b1 = anchor_e[2] * anchor[6] - anchor_e[0] * anchor[8];
206
c1 = anchor_e[0] * anchor[7] - anchor_e[1] * anchor[6];
207
a2 = anchor_e[1] * anchor[2] - anchor_e[2] * anchor[1];
208
b2 = anchor_e[2] * anchor[0] - anchor_e[0] * anchor[2];
209
c2 = anchor_e[0] * anchor[1] - anchor_e[1] * anchor[0];
210
inflection = (anchor_e[2] / anchor_e[1]);
212
case tritanopeVision:
213
/* Set 1: regions where lambda_a=575, set 2: lambda_a=475 */
214
a1 = anchor_e[1] * anchor[11] - anchor_e[2] * anchor[10];
215
b1 = anchor_e[2] * anchor[9] - anchor_e[0] * anchor[11];
216
c1 = anchor_e[0] * anchor[10] - anchor_e[1] * anchor[9];
217
a2 = anchor_e[1] * anchor[5] - anchor_e[2] * anchor[4];
218
b2 = anchor_e[2] * anchor[3] - anchor_e[0] * anchor[5];
219
c2 = anchor_e[0] * anchor[4] - anchor_e[1] * anchor[3];
220
inflection = (anchor_e[1] / anchor_e[0]);
225
uint VisionDefectColor::getRed()
230
uint VisionDefectColor::getGreen()
235
uint VisionDefectColor::getBlue()
240
QColor VisionDefectColor::getColor()
242
return QColor(getRed(), getGreen(), getBlue());
245
double VisionDefectColor::clamp(double x, double low, double high)
248
(x > high) ? ret = high : ((x < low) ? ret = low : ret = x);