~ubuntu-branches/ubuntu/trusty/scribus-ng/trusty

« back to all changes in this revision

Viewing changes to scribus/colorblind.cpp

  • Committer: Package Import Robot
  • Author(s): Oleksandr Moskalenko
  • Date: 2012-02-15 15:57:12 UTC
  • mfrom: (4.2.10 sid)
  • Revision ID: package-import@ubuntu.com-20120215155712-biimoc8o875jht80
Tags: 1.4.0.dfsg+r17300-1
* Prepare a dummy transitional package to converge on the 1.4.0 release.
* debian/NEWS: update the news.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
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.
6
 
*/
7
 
#include "colorblind.h"
8
 
//#include "colorblind.moc"
9
 
 
10
 
#include <math.h>
11
 
 
12
 
//#define CLAMP(x, low, high)  (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
13
 
 
14
 
 
15
 
VisionDefectColor::VisionDefectColor(int r, int g, int b)
16
 
{
17
 
        red = (double)r;
18
 
        green = (double)g;
19
 
        blue = (double)b;
20
 
        originalColor = QColor(r, g, b);
21
 
        init();
22
 
}
23
 
 
24
 
VisionDefectColor::VisionDefectColor(QColor c)
25
 
{
26
 
        red = (double)c.red();
27
 
        green = (double)c.green();
28
 
        blue = (double)c.blue();
29
 
        originalColor = c;
30
 
        init();
31
 
}
32
 
 
33
 
VisionDefectColor::VisionDefectColor()
34
 
{
35
 
        red = 0.0;
36
 
        green = 0.0;
37
 
        blue = 0.0;
38
 
        originalColor = QColor(0, 0, 0);
39
 
        init();
40
 
}
41
 
 
42
 
void VisionDefectColor::init()
43
 
{
44
 
        rgb2lms[0] = 0.05059983;
45
 
        rgb2lms[1] = 0.08585369;
46
 
        rgb2lms[2] = 0.00952420;
47
 
 
48
 
        rgb2lms[3] = 0.01893033;
49
 
        rgb2lms[4] = 0.08925308;
50
 
        rgb2lms[5] = 0.01370054;
51
 
 
52
 
        rgb2lms[6] = 0.00292202;
53
 
        rgb2lms[7] = 0.00975732;
54
 
        rgb2lms[8] = 0.07145979;
55
 
 
56
 
        lms2rgb[0] =    30.830854;
57
 
        lms2rgb[1] = -29.832659;
58
 
        lms2rgb[2] =     1.610474;
59
 
 
60
 
        lms2rgb[3] =    -6.481468;
61
 
        lms2rgb[4] =    17.715578;
62
 
        lms2rgb[5] =    -2.532642;
63
 
 
64
 
        lms2rgb[6] =    -0.375690;
65
 
        lms2rgb[7] =    -1.199062;
66
 
        lms2rgb[8] =    14.273846;
67
 
 
68
 
        gammaRGB[0] = 2.1;
69
 
        gammaRGB[1] = 2.0;
70
 
        gammaRGB[2] = 2.1;
71
 
}
72
 
 
73
 
void VisionDefectColor::convertDefect()
74
 
{
75
 
        double tmp;
76
 
 
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]);
81
 
 
82
 
        /* Convert to LMS (dot product with transform matrix) */
83
 
        double redOld   = red;
84
 
        double greenOld = green;
85
 
 
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];
89
 
 
90
 
        switch (deficiency)
91
 
        {
92
 
                case normalVision:
93
 
                        break;
94
 
                case deuteranopeVision:
95
 
                        setupDefect();
96
 
                        tmp = blue / red;
97
 
                        /* See which side of the inflection line we fall... */
98
 
                        if (tmp < inflection)
99
 
                                green = -(a1 * red + c1 * blue) / b1;
100
 
                        else
101
 
                                green = -(a2 * red + c2 * blue) / b2;
102
 
                        break;
103
 
                case protanopeVision:
104
 
                        setupDefect();
105
 
                        tmp = blue / green;
106
 
                        /* See which side of the inflection line we fall... */
107
 
                        if (tmp < inflection)
108
 
                                red = -(b1 * green + c1 * blue) / a1;
109
 
                        else
110
 
                                red = -(b2 * green + c2 * blue) / a2;
111
 
                        break;
112
 
                case tritanopeVision:
113
 
                        setupDefect();
114
 
                        tmp = green / red;
115
 
                        /* See which side of the inflection line we fall... */
116
 
                        if (tmp < inflection)
117
 
                                blue = -(a1 * red + b1 * green) / c1;
118
 
                        else
119
 
                                blue = -(a2 * red + b2 * green) / c2;
120
 
                        break;
121
 
                case colorBlindnessVision:
122
 
                {
123
 
                        double gray = clamp(0.3 * originalColor.red()
124
 
                                                + 0.59 * originalColor.green()
125
 
                                                + 0.11 * originalColor.blue(), 0, 255);
126
 
                        red = gray;
127
 
                        green = gray;
128
 
                        blue = gray;
129
 
                        return; // no other transformations!
130
 
                }
131
 
                default:
132
 
                        break;
133
 
        }
134
 
 
135
 
        /* Convert back to RGB (cross product with transform matrix) */
136
 
        redOld   = red;
137
 
        greenOld = green;
138
 
 
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];
142
 
 
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]);
147
 
 
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);
153
 
}
154
 
 
155
 
QColor VisionDefectColor::convertDefect(QColor c, int d)
156
 
{
157
 
        red = (double)c.red();
158
 
        green = (double)c.green();
159
 
        blue = (double)c.blue();
160
 
        originalColor = c;
161
 
        init();
162
 
        deficiency = d;
163
 
        convertDefect();
164
 
        return getColor();
165
 
}
166
 
 
167
 
void VisionDefectColor::setupDefect()
168
 
{
169
 
        double anchor_e[3];
170
 
        double anchor[12];
171
 
 
172
 
        /*
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
175
 
        (for tritans)
176
 
        */
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;
181
 
 
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
184
 
        * matrix)
185
 
        */
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];
189
 
 
190
 
        switch (deficiency)
191
 
        {
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]);
201
 
                        break;
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]);
211
 
                        break;
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]);
221
 
                        break;
222
 
        }
223
 
}
224
 
 
225
 
uint VisionDefectColor::getRed()
226
 
{
227
 
        return (uint)red;
228
 
}
229
 
 
230
 
uint VisionDefectColor::getGreen()
231
 
{
232
 
        return (uint)green;
233
 
}
234
 
 
235
 
uint VisionDefectColor::getBlue()
236
 
{
237
 
        return (uint)blue;
238
 
}
239
 
 
240
 
QColor VisionDefectColor::getColor()
241
 
{
242
 
        return QColor(getRed(), getGreen(), getBlue());
243
 
}
244
 
 
245
 
double VisionDefectColor::clamp(double x, double low, double high)
246
 
{
247
 
        double ret;
248
 
        (x > high) ? ret = high : ((x < low) ? ret = low : ret = x);
249
 
        return ret;
250
 
}