Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(70)

Side by Side Diff: src/core/SkColorSpace.cpp

Issue 1695353002: starter kit for colorspaces (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/core/SkColorSpace.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "SkAtomics.h"
9 #include "SkColorSpace.h"
10
11 static inline bool SkFloatIsFinite(float x) { return 0 == x * 0; }
12
13 //
14 // SkFloat3x3
15 //
16 // In memory order, values are a, b, c, d, e, f, g, h, i
17 //
18 // When applied to a color component vector (e.g. [ r, r, r ] or [ g, g, g ] we do
19 //
20 // [ r r r ] * [ a b c ] + [ g g g ] * [ d e f ] + [ b b b ] * [ g h i ]
21 //
22 // Thus in our point-on-the-right notation, the matrix looks like
23 //
24 // [ a d g ] [ r ]
25 // [ b e h ] * [ g ]
26 // [ c f i ] [ b ]
27 //
28 static SkFloat3x3 concat(const SkFloat3x3& left, const SkFloat3x3& rite) {
29 SkFloat3x3 result;
30 for (int row = 0; row < 3; ++row) {
31 for (int col = 0; col < 3; ++col) {
32 double tmp = 0;
33 for (int i = 0; i < 3; ++i) {
34 tmp += (double)left.fMat[row + i * 3] * rite.fMat[i + col * 3];
35 }
36 result.fMat[row + col * 3] = (double)tmp;
37 }
38 }
39 return result;
40 }
41
42 static double det(const SkFloat3x3& m) {
43 return (double)m.fMat[0] * m.fMat[4] * m.fMat[8] +
44 (double)m.fMat[3] * m.fMat[7] * m.fMat[2] +
45 (double)m.fMat[6] * m.fMat[1] * m.fMat[5] -
46 (double)m.fMat[0] * m.fMat[7] * m.fMat[5] -
47 (double)m.fMat[3] * m.fMat[1] * m.fMat[8] -
48 (double)m.fMat[6] * m.fMat[4] * m.fMat[2];
49 }
50
51 static double det2x2(const SkFloat3x3& m, int a, int b, int c, int d) {
52 return (double)m.fMat[a] * m.fMat[b] - (double)m.fMat[c] * m.fMat[d];
53 }
54
55 static SkFloat3x3 invert(const SkFloat3x3& m) {
56 double d = det(m);
57 SkASSERT(SkFloatIsFinite((float)d));
58 double scale = 1 / d;
59 SkASSERT(SkFloatIsFinite((float)scale));
60
61 return {{
62 (float)(scale * det2x2(m, 4, 8, 5, 7)),
63 (float)(scale * det2x2(m, 7, 2, 8, 1)),
64 (float)(scale * det2x2(m, 1, 5, 2, 4)),
65
66 (float)(scale * det2x2(m, 6, 5, 8, 3)),
67 (float)(scale * det2x2(m, 0, 8, 2, 6)),
68 (float)(scale * det2x2(m, 3, 2, 5, 0)),
69
70 (float)(scale * det2x2(m, 3, 7, 4, 6)),
71 (float)(scale * det2x2(m, 6, 1, 7, 0)),
72 (float)(scale * det2x2(m, 0, 4, 1, 3)),
73 }};
74 }
75
76 void SkFloat3::dump() const {
77 SkDebugf("[%7.4f %7.4f %7.4f]\n", fVec[0], fVec[1], fVec[2]);
78 }
79
80 void SkFloat3x3::dump() const {
81 SkDebugf("[%7.4f %7.4f %7.4f] [%7.4f %7.4f %7.4f] [%7.4f %7.4f %7.4f]\n",
82 fMat[0], fMat[1], fMat[2],
83 fMat[3], fMat[4], fMat[5],
84 fMat[6], fMat[7], fMat[8]);
85 }
86
87 //////////////////////////////////////////////////////////////////////////////// //////////////////
88
89 static int32_t gUniqueColorSpaceID;
90
91 SkColorSpace::SkColorSpace(const SkFloat3x3& toXYZD50, const SkFloat3& gamma, Na med named)
92 : fToXYZD50(toXYZD50)
93 , fGamma(gamma)
94 , fUniqueID(sk_atomic_inc(&gUniqueColorSpaceID))
95 , fNamed(named)
96 {
97 for (int i = 0; i < 3; ++i) {
98 SkASSERT(SkFloatIsFinite(gamma.fVec[i]));
99 for (int j = 0; j < 3; ++j) {
100 SkASSERT(SkFloatIsFinite(toXYZD50.fMat[3*i + j]));
101 }
102 }
103 }
104
105 SkColorSpace* SkColorSpace::NewRGB(const SkFloat3x3& toXYZD50, const SkFloat3& g amma) {
106 for (int i = 0; i < 3; ++i) {
107 if (!SkFloatIsFinite(gamma.fVec[i]) || gamma.fVec[i] < 0) {
108 return nullptr;
109 }
110 for (int j = 0; j < 3; ++j) {
111 if (!SkFloatIsFinite(toXYZD50.fMat[3*i + j])) {
112 return nullptr;
113 }
114 }
115 }
116
117 // check the matrix for invertibility
118 float d = det(toXYZD50);
119 if (!SkFloatIsFinite(d) || !SkFloatIsFinite(1 / d)) {
120 return nullptr;
121 }
122
123 return new SkColorSpace(toXYZD50, gamma, kUnknown_Named);
124 }
125
126 void SkColorSpace::dump() const {
127 fToXYZD50.dump();
128 fGamma.dump();
129 }
130
131 //////////////////////////////////////////////////////////////////////////////// //////////////////
132
133 const SkFloat3 gDevice_gamma {{ 0, 0, 0 }};
134 const SkFloat3x3 gDevice_toXYZD50 {{
135 1, 0, 0,
136 0, 1, 0,
137 0, 0, 1
138 }};
139
140 const SkFloat3 gSRGB_gamma {{ 2.2f, 2.2f, 2.2f }};
141 const SkFloat3x3 gSRGB_toXYZD50 {{
142 0.4358f, 0.2224f, 0.0139f, // * R
143 0.3853f, 0.7170f, 0.0971f, // * G
144 0.1430f, 0.0606f, 0.7139f, // * B
145 }};
146
147 SkColorSpace* SkColorSpace::NewNamed(Named named) {
148 switch (named) {
149 case kDevice_Named:
150 return new SkColorSpace(gDevice_toXYZD50, gDevice_gamma, kDevice_Nam ed);
151 case kSRGB_Named:
152 return new SkColorSpace(gSRGB_toXYZD50, gSRGB_gamma, kSRGB_Named);
153 default:
154 break;
155 }
156 return nullptr;
157 }
158
159 //////////////////////////////////////////////////////////////////////////////// ///////////////////
160
161 SkColorSpace::Result SkColorSpace::Concat(const SkColorSpace* src, const SkColor Space* dst,
162 SkFloat3x3* result) {
163 if (!src || !dst || (src->named() == kDevice_Named) || (src->named() == dst- >named())) {
164 if (result) {
165 *result = {{ 1, 0, 0, 0, 1, 0, 0, 0, 1 }};
166 }
167 return kIdentity_Result;
168 }
169 if (result) {
170 *result = concat(src->fToXYZD50, invert(dst->fToXYZD50));
171 }
172 return kNormal_Result;
173 }
174
175 #include "SkColor.h"
176 #include "SkNx.h"
177
178 void SkApply3x3ToPM4f(const SkFloat3x3& m, const SkPM4f src[], SkPM4f dst[], int count) {
179 SkASSERT(1 == SkPM4f::G);
180 SkASSERT(3 == SkPM4f::A);
181
182 Sk4f cr, cg, cb;
183 cg = Sk4f::Load(m.fMat + 3);
184 if (0 == SkPM4f::R) {
185 SkASSERT(2 == SkPM4f::B);
186 cr = Sk4f::Load(m.fMat + 0);
187 cb = Sk4f(m.fMat[6], m.fMat[7], m.fMat[8], 0);
188 } else {
189 SkASSERT(0 == SkPM4f::B);
190 SkASSERT(2 == SkPM4f::R);
191 cb = Sk4f::Load(m.fMat + 0);
192 cr = Sk4f(m.fMat[6], m.fMat[7], m.fMat[8], 0);
193 }
194 cr = cr * Sk4f(1, 1, 1, 0);
195 cg = cg * Sk4f(1, 1, 1, 0);
196 cb = cb * Sk4f(1, 1, 1, 0);
197
198 for (int i = 0; i < count; ++i) {
199 Sk4f r = Sk4f(src[i].fVec[SkPM4f::R]);
200 Sk4f g = Sk4f(src[i].fVec[SkPM4f::G]);
201 Sk4f b = Sk4f(src[i].fVec[SkPM4f::B]);
202 Sk4f a = Sk4f(0, 0, 0, src[i].fVec[SkPM4f::A]);
203 (cr * r + cg * g + cb * b + a).store(&dst[i]);
204 }
205 }
206
207 //////////////////////////////////////////////////////////////////////////////// ///////////////////
208
209 void SkColorSpace::Test() {
210 SkFloat3x3 mat {{ 2, 0, 0, 0, 3, 0, 0, 0, 4 }};
211 SkFloat3x3 inv = invert(mat);
212 mat.dump();
213 inv.dump();
214 concat(mat, inv).dump();
215 concat(inv, mat).dump();
216 SkDebugf("\n");
217
218 mat = gSRGB_toXYZD50;
219 inv = invert(mat);
220 mat.dump();
221 inv.dump();
222 concat(mat, inv).dump();
223 concat(inv, mat).dump();
224 SkDebugf("\n");
225
226 SkAutoTUnref<SkColorSpace> cs0(SkColorSpace::NewNamed(SkColorSpace::kSRGB_Na med));
227 SkAutoTUnref<SkColorSpace> cs1(SkColorSpace::NewNamed(SkColorSpace::kSRGB_Na med));
228
229 cs0->dump();
230 cs1->dump();
231 SkFloat3x3 xform;
232 (void)SkColorSpace::Concat(cs0, cs1, &xform);
233 xform.dump();
234 SkDebugf("\n");
235 }
236
237 // D65 white point of Rec. 709 [8] are:
238 //
239 // D65 white-point in unit luminance XYZ = 0.9505, 1.0000, 1.0890
240 //
241 // R G B white
242 // x 0.640 0.300 0.150 0.3127
243 // y 0.330 0.600 0.060 0.3290
244 // z 0.030 0.100 0.790 0.3582
OLDNEW
« no previous file with comments | « src/core/SkColorSpace.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698