OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkColorPriv.h" | 8 #include "SkColorPriv.h" |
9 #include "SkColorSpace_Base.h" | 9 #include "SkColorSpace_Base.h" |
10 #include "SkColorSpaceXform.h" | 10 #include "SkColorSpaceXform.h" |
11 #include "SkOpts.h" | 11 #include "SkOpts.h" |
12 #include "SkSRGB.h" | 12 #include "SkSRGB.h" |
13 | 13 |
14 static inline bool compute_gamut_xform(SkMatrix44* srcToDst, const SkMatrix44& s
rcToXYZ, | 14 static constexpr float sk_linear_from_2dot2[256] = { |
15 const SkMatrix44& dstToXYZ) { | |
16 if (!dstToXYZ.invert(srcToDst)) { | |
17 return false; | |
18 } | |
19 | |
20 srcToDst->postConcat(srcToXYZ); | |
21 return true; | |
22 } | |
23 | |
24 std::unique_ptr<SkColorSpaceXform> SkColorSpaceXform::New(const sk_sp<SkColorSpa
ce>& srcSpace, | |
25 const sk_sp<SkColorSpa
ce>& dstSpace) { | |
26 if (!srcSpace || !dstSpace) { | |
27 // Invalid input | |
28 return nullptr; | |
29 } | |
30 | |
31 if (as_CSB(dstSpace)->colorLUT()) { | |
32 // It would be really weird for a dst profile to have a color LUT. I do
n't think | |
33 // we need to support this. | |
34 return nullptr; | |
35 } | |
36 | |
37 SkMatrix44 srcToDst(SkMatrix44::kUninitialized_Constructor); | |
38 if (!compute_gamut_xform(&srcToDst, srcSpace->xyz(), dstSpace->xyz())) { | |
39 return nullptr; | |
40 } | |
41 | |
42 if (0.0f == srcToDst.getFloat(3, 0) && | |
43 0.0f == srcToDst.getFloat(3, 1) && | |
44 0.0f == srcToDst.getFloat(3, 2) && | |
45 !as_CSB(srcSpace)->colorLUT()) | |
46 { | |
47 switch (srcSpace->gammaNamed()) { | |
48 case SkColorSpace::kSRGB_GammaNamed: | |
49 if (SkColorSpace::kSRGB_GammaNamed == dstSpace->gammaNamed()) { | |
50 return std::unique_ptr<SkColorSpaceXform>( | |
51 new SkFastXform<SkColorSpace::kSRGB_GammaNamed, | |
52 SkColorSpace::kSRGB_GammaNamed>(srcT
oDst)); | |
53 } else if (SkColorSpace::k2Dot2Curve_GammaNamed == dstSpace->gam
maNamed()) { | |
54 return std::unique_ptr<SkColorSpaceXform>( | |
55 new SkFastXform<SkColorSpace::kSRGB_GammaNamed, | |
56 SkColorSpace::k2Dot2Curve_GammaNamed
>(srcToDst)); | |
57 } | |
58 break; | |
59 case SkColorSpace::k2Dot2Curve_GammaNamed: | |
60 if (SkColorSpace::kSRGB_GammaNamed == dstSpace->gammaNamed()) { | |
61 return std::unique_ptr<SkColorSpaceXform>( | |
62 new SkFastXform<SkColorSpace::k2Dot2Curve_GammaNamed
, | |
63 SkColorSpace::kSRGB_GammaNamed>(srcT
oDst)); | |
64 } else if (SkColorSpace::k2Dot2Curve_GammaNamed == dstSpace->gam
maNamed()) { | |
65 return std::unique_ptr<SkColorSpaceXform>( | |
66 new SkFastXform<SkColorSpace::k2Dot2Curve_GammaNamed
, | |
67 SkColorSpace::k2Dot2Curve_GammaNamed
>(srcToDst)); | |
68 } | |
69 break; | |
70 default: | |
71 break; | |
72 } | |
73 } | |
74 | |
75 return std::unique_ptr<SkColorSpaceXform>(new SkDefaultXform(srcSpace, srcTo
Dst, dstSpace)); | |
76 } | |
77 | |
78 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | |
79 | |
80 static void build_src_to_dst(float srcToDstArray[12], const SkMatrix44& srcToDst
Matrix) { | |
81 // Build the following row major matrix: | |
82 // rX gX bX 0 | |
83 // rY gY bY 0 | |
84 // rZ gZ bZ 0 | |
85 // Swap R and B if necessary to make sure that we output SkPMColor order. | |
86 #ifdef SK_PMCOLOR_IS_BGRA | |
87 srcToDstArray[0] = srcToDstMatrix.getFloat(0, 2); | |
88 srcToDstArray[1] = srcToDstMatrix.getFloat(0, 1); | |
89 srcToDstArray[2] = srcToDstMatrix.getFloat(0, 0); | |
90 srcToDstArray[3] = 0.0f; | |
91 srcToDstArray[4] = srcToDstMatrix.getFloat(1, 2); | |
92 srcToDstArray[5] = srcToDstMatrix.getFloat(1, 1); | |
93 srcToDstArray[6] = srcToDstMatrix.getFloat(1, 0); | |
94 srcToDstArray[7] = 0.0f; | |
95 srcToDstArray[8] = srcToDstMatrix.getFloat(2, 2); | |
96 srcToDstArray[9] = srcToDstMatrix.getFloat(2, 1); | |
97 srcToDstArray[10] = srcToDstMatrix.getFloat(2, 0); | |
98 srcToDstArray[11] = 0.0f; | |
99 #else | |
100 srcToDstArray[0] = srcToDstMatrix.getFloat(0, 0); | |
101 srcToDstArray[1] = srcToDstMatrix.getFloat(0, 1); | |
102 srcToDstArray[2] = srcToDstMatrix.getFloat(0, 2); | |
103 srcToDstArray[3] = 0.0f; | |
104 srcToDstArray[4] = srcToDstMatrix.getFloat(1, 0); | |
105 srcToDstArray[5] = srcToDstMatrix.getFloat(1, 1); | |
106 srcToDstArray[6] = srcToDstMatrix.getFloat(1, 2); | |
107 srcToDstArray[7] = 0.0f; | |
108 srcToDstArray[8] = srcToDstMatrix.getFloat(2, 0); | |
109 srcToDstArray[9] = srcToDstMatrix.getFloat(2, 1); | |
110 srcToDstArray[10] = srcToDstMatrix.getFloat(2, 2); | |
111 srcToDstArray[11] = 0.0f; | |
112 #endif | |
113 } | |
114 | |
115 template <SkColorSpace::GammaNamed Src, SkColorSpace::GammaNamed Dst> | |
116 SkFastXform<Src, Dst>::SkFastXform(const SkMatrix44& srcToDst) | |
117 { | |
118 build_src_to_dst(fSrcToDst, srcToDst); | |
119 } | |
120 | |
121 template <> | |
122 void SkFastXform<SkColorSpace::kSRGB_GammaNamed, SkColorSpace::kSRGB_GammaNamed> | |
123 ::xform_RGB1_8888(uint32_t* dst, const uint32_t* src, uint32_t len) const | |
124 { | |
125 SkOpts::color_xform_RGB1_srgb_to_srgb(dst, src, len, fSrcToDst); | |
126 } | |
127 | |
128 template <> | |
129 void SkFastXform<SkColorSpace::kSRGB_GammaNamed, SkColorSpace::k2Dot2Curve_Gamma
Named> | |
130 ::xform_RGB1_8888(uint32_t* dst, const uint32_t* src, uint32_t len) const | |
131 { | |
132 SkOpts::color_xform_RGB1_srgb_to_2dot2(dst, src, len, fSrcToDst); | |
133 } | |
134 | |
135 template <> | |
136 void SkFastXform<SkColorSpace::k2Dot2Curve_GammaNamed, SkColorSpace::kSRGB_Gamma
Named> | |
137 ::xform_RGB1_8888(uint32_t* dst, const uint32_t* src, uint32_t len) const | |
138 { | |
139 SkOpts::color_xform_RGB1_2dot2_to_srgb(dst, src, len, fSrcToDst); | |
140 } | |
141 | |
142 template <> | |
143 void SkFastXform<SkColorSpace::k2Dot2Curve_GammaNamed, SkColorSpace::k2Dot2Curve
_GammaNamed> | |
144 ::xform_RGB1_8888(uint32_t* dst, const uint32_t* src, uint32_t len) const | |
145 { | |
146 SkOpts::color_xform_RGB1_2dot2_to_2dot2(dst, src, len, fSrcToDst); | |
147 } | |
148 | |
149 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | |
150 | |
151 extern const float sk_linear_from_2dot2[256] = { | |
152 0.000000000000000000f, 0.000005077051900662f, 0.000023328004666099f, 0.0
00056921765712193f, | 15 0.000000000000000000f, 0.000005077051900662f, 0.000023328004666099f, 0.0
00056921765712193f, |
153 0.000107187362341244f, 0.000175123977503027f, 0.000261543754548491f, 0.0
00367136269815943f, | 16 0.000107187362341244f, 0.000175123977503027f, 0.000261543754548491f, 0.0
00367136269815943f, |
154 0.000492503787191433f, 0.000638182842167022f, 0.000804658499513058f, 0.0
00992374304074325f, | 17 0.000492503787191433f, 0.000638182842167022f, 0.000804658499513058f, 0.0
00992374304074325f, |
155 0.001201739522438400f, 0.001433134589671860f, 0.001686915316789280f, 0.0
01963416213396470f, | 18 0.001201739522438400f, 0.001433134589671860f, 0.001686915316789280f, 0.0
01963416213396470f, |
156 0.002262953160706430f, 0.002585825596234170f, 0.002932318323938360f, 0.0
03302703032003640f, | 19 0.002262953160706430f, 0.002585825596234170f, 0.002932318323938360f, 0.0
03302703032003640f, |
157 0.003697239578900130f, 0.004116177093282750f, 0.004559754922526020f, 0.0
05028203456855540f, | 20 0.003697239578900130f, 0.004116177093282750f, 0.004559754922526020f, 0.0
05028203456855540f, |
158 0.005521744850239660f, 0.006040593654849810f, 0.006584957382581690f, 0.0
07155037004573030f, | 21 0.005521744850239660f, 0.006040593654849810f, 0.006584957382581690f, 0.0
07155037004573030f, |
159 0.007751027397660610f, 0.008373117745148580f, 0.009021491898012130f, 0.0
09696328701658230f, | 22 0.007751027397660610f, 0.008373117745148580f, 0.009021491898012130f, 0.0
09696328701658230f, |
160 0.010397802292555300f, 0.011126082368383200f, 0.011881334434813700f, 0.0
12663720031582100f, | 23 0.010397802292555300f, 0.011126082368383200f, 0.011881334434813700f, 0.0
12663720031582100f, |
161 0.013473396940142600f, 0.014310519374884100f, 0.015175238159625200f, 0.0
16067700890886900f, | 24 0.013473396940142600f, 0.014310519374884100f, 0.015175238159625200f, 0.0
16067700890886900f, |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
248 // Y = eX + f otherwise | 111 // Y = eX + f otherwise |
249 for (float x = 0.0f; x <= 1.0f; x += (1.0f/255.0f)) { | 112 for (float x = 0.0f; x <= 1.0f; x += (1.0f/255.0f)) { |
250 if (x >= d) { | 113 if (x >= d) { |
251 *outTable++ = powf(a * x + b, g) + c; | 114 *outTable++ = powf(a * x + b, g) + c; |
252 } else { | 115 } else { |
253 *outTable++ = e * x + f; | 116 *outTable++ = e * x + f; |
254 } | 117 } |
255 } | 118 } |
256 } | 119 } |
257 | 120 |
| 121 static inline bool compute_gamut_xform(SkMatrix44* srcToDst, const SkMatrix44& s
rcToXYZ, |
| 122 const SkMatrix44& dstToXYZ) { |
| 123 if (!dstToXYZ.invert(srcToDst)) { |
| 124 return false; |
| 125 } |
| 126 |
| 127 srcToDst->postConcat(srcToXYZ); |
| 128 return true; |
| 129 } |
| 130 |
| 131 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
| 132 |
258 static constexpr uint8_t linear_to_srgb[1024] = { | 133 static constexpr uint8_t linear_to_srgb[1024] = { |
259 0, 3, 6, 10, 13, 15, 18, 20, 22, 23, 25, 27, 28, 30, 3
1, 32, 34, 35, | 134 0, 3, 6, 10, 13, 15, 18, 20, 22, 23, 25, 27, 28, 30, 3
1, 32, 34, 35, |
260 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 4
9, 50, 51, 52, | 135 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 4
9, 50, 51, 52, |
261 53, 53, 54, 55, 56, 56, 57, 58, 58, 59, 60, 61, 61, 62, 6
2, 63, 64, 64, | 136 53, 53, 54, 55, 56, 56, 57, 58, 58, 59, 60, 61, 61, 62, 6
2, 63, 64, 64, |
262 65, 66, 66, 67, 67, 68, 68, 69, 70, 70, 71, 71, 72, 72, 7
3, 73, 74, 74, | 137 65, 66, 66, 67, 67, 68, 68, 69, 70, 70, 71, 71, 72, 72, 7
3, 73, 74, 74, |
263 75, 76, 76, 77, 77, 78, 78, 79, 79, 79, 80, 80, 81, 81, 8
2, 82, 83, 83, | 138 75, 76, 76, 77, 77, 78, 78, 79, 79, 79, 80, 80, 81, 81, 8
2, 82, 83, 83, |
264 84, 84, 85, 85, 85, 86, 86, 87, 87, 88, 88, 88, 89, 89, 9
0, 90, 91, 91, | 139 84, 84, 85, 85, 85, 86, 86, 87, 87, 88, 88, 88, 89, 89, 9
0, 90, 91, 91, |
265 91, 92, 92, 93, 93, 93, 94, 94, 95, 95, 95, 96, 96, 97, 9
7, 97, 98, 98, | 140 91, 92, 92, 93, 93, 93, 94, 94, 95, 95, 95, 96, 96, 97, 9
7, 97, 98, 98, |
266 98, 99, 99, 99, 100, 100, 101, 101, 101, 102, 102, 102, 103, 103, 10
3, 104, 104, 104, | 141 98, 99, 99, 99, 100, 100, 101, 101, 101, 102, 102, 102, 103, 103, 10
3, 104, 104, 104, |
267 105, 105, 106, 106, 106, 107, 107, 107, 108, 108, 108, 109, 109, 109, 11
0, 110, 110, 110, | 142 105, 105, 106, 106, 106, 107, 107, 107, 108, 108, 108, 109, 109, 109, 11
0, 110, 110, 110, |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
466 | 341 |
467 static void build_table_linear_to_gamma(uint8_t* outTable, int outTableSize, flo
at g, float a, | 342 static void build_table_linear_to_gamma(uint8_t* outTable, int outTableSize, flo
at g, float a, |
468 float b, float c, float d, float e, floa
t f) { | 343 float b, float c, float d, float e, floa
t f) { |
469 for (int i = 0; i < outTableSize; i++) { | 344 for (int i = 0; i < outTableSize; i++) { |
470 float x = ((float) i) * (1.0f / ((float) (outTableSize - 1))); | 345 float x = ((float) i) * (1.0f / ((float) (outTableSize - 1))); |
471 float y = inverse_parametric(x, g, a, b, c, d, e, f); | 346 float y = inverse_parametric(x, g, a, b, c, d, e, f); |
472 outTable[i] = clamp_normalized_float_to_byte(y); | 347 outTable[i] = clamp_normalized_float_to_byte(y); |
473 } | 348 } |
474 } | 349 } |
475 | 350 |
| 351 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
| 352 |
| 353 std::unique_ptr<SkColorSpaceXform> SkColorSpaceXform::New(const sk_sp<SkColorSpa
ce>& srcSpace, |
| 354 const sk_sp<SkColorSpa
ce>& dstSpace) { |
| 355 if (!srcSpace || !dstSpace) { |
| 356 // Invalid input |
| 357 return nullptr; |
| 358 } |
| 359 |
| 360 if (as_CSB(dstSpace)->colorLUT()) { |
| 361 // It would be really weird for a dst profile to have a color LUT. I do
n't think |
| 362 // we need to support this. |
| 363 return nullptr; |
| 364 } |
| 365 |
| 366 SkMatrix44 srcToDst(SkMatrix44::kUninitialized_Constructor); |
| 367 if (!compute_gamut_xform(&srcToDst, srcSpace->xyz(), dstSpace->xyz())) { |
| 368 return nullptr; |
| 369 } |
| 370 |
| 371 if (0.0f == srcToDst.getFloat(3, 0) && |
| 372 0.0f == srcToDst.getFloat(3, 1) && |
| 373 0.0f == srcToDst.getFloat(3, 2) && |
| 374 !as_CSB(srcSpace)->colorLUT()) |
| 375 { |
| 376 switch (dstSpace->gammaNamed()) { |
| 377 case SkColorSpace::kSRGB_GammaNamed: |
| 378 return std::unique_ptr<SkColorSpaceXform>( |
| 379 new SkFastXform<SkColorSpace::kSRGB_GammaNamed>(srcSpace
, srcToDst, |
| 380 dstSpace
)); |
| 381 case SkColorSpace::k2Dot2Curve_GammaNamed: |
| 382 return std::unique_ptr<SkColorSpaceXform>( |
| 383 new SkFastXform<SkColorSpace::k2Dot2Curve_GammaNamed>(sr
cSpace, srcToDst, |
| 384 ds
tSpace)); |
| 385 default: |
| 386 return std::unique_ptr<SkColorSpaceXform>( |
| 387 new SkFastXform<SkColorSpace::kNonStandard_GammaNamed>(s
rcSpace, srcToDst, |
| 388 d
stSpace)); |
| 389 } |
| 390 } |
| 391 |
| 392 return std::unique_ptr<SkColorSpaceXform>(new SkDefaultXform(srcSpace, srcTo
Dst, dstSpace)); |
| 393 } |
| 394 |
| 395 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
| 396 |
| 397 static void build_src_to_dst(float srcToDstArray[12], const SkMatrix44& srcToDst
Matrix) { |
| 398 // Build the following row major matrix: |
| 399 // rX gX bX 0 |
| 400 // rY gY bY 0 |
| 401 // rZ gZ bZ 0 |
| 402 // Swap R and B if necessary to make sure that we output SkPMColor order. |
| 403 #ifdef SK_PMCOLOR_IS_BGRA |
| 404 srcToDstArray[0] = srcToDstMatrix.getFloat(0, 2); |
| 405 srcToDstArray[1] = srcToDstMatrix.getFloat(0, 1); |
| 406 srcToDstArray[2] = srcToDstMatrix.getFloat(0, 0); |
| 407 srcToDstArray[3] = 0.0f; |
| 408 srcToDstArray[4] = srcToDstMatrix.getFloat(1, 2); |
| 409 srcToDstArray[5] = srcToDstMatrix.getFloat(1, 1); |
| 410 srcToDstArray[6] = srcToDstMatrix.getFloat(1, 0); |
| 411 srcToDstArray[7] = 0.0f; |
| 412 srcToDstArray[8] = srcToDstMatrix.getFloat(2, 2); |
| 413 srcToDstArray[9] = srcToDstMatrix.getFloat(2, 1); |
| 414 srcToDstArray[10] = srcToDstMatrix.getFloat(2, 0); |
| 415 srcToDstArray[11] = 0.0f; |
| 416 #else |
| 417 srcToDstArray[0] = srcToDstMatrix.getFloat(0, 0); |
| 418 srcToDstArray[1] = srcToDstMatrix.getFloat(0, 1); |
| 419 srcToDstArray[2] = srcToDstMatrix.getFloat(0, 2); |
| 420 srcToDstArray[3] = 0.0f; |
| 421 srcToDstArray[4] = srcToDstMatrix.getFloat(1, 0); |
| 422 srcToDstArray[5] = srcToDstMatrix.getFloat(1, 1); |
| 423 srcToDstArray[6] = srcToDstMatrix.getFloat(1, 2); |
| 424 srcToDstArray[7] = 0.0f; |
| 425 srcToDstArray[8] = srcToDstMatrix.getFloat(2, 0); |
| 426 srcToDstArray[9] = srcToDstMatrix.getFloat(2, 1); |
| 427 srcToDstArray[10] = srcToDstMatrix.getFloat(2, 2); |
| 428 srcToDstArray[11] = 0.0f; |
| 429 #endif |
| 430 } |
| 431 |
| 432 template <SkColorSpace::GammaNamed Dst> |
| 433 SkFastXform<Dst>::SkFastXform(const sk_sp<SkColorSpace>& srcSpace, const SkMatri
x44& srcToDst, |
| 434 const sk_sp<SkColorSpace>& dstSpace) |
| 435 { |
| 436 build_src_to_dst(fSrcToDst, srcToDst); |
| 437 |
| 438 // Build tables to transform src gamma to linear. |
| 439 switch (srcSpace->gammaNamed()) { |
| 440 case SkColorSpace::kSRGB_GammaNamed: |
| 441 fSrcGammaTables[0] = fSrcGammaTables[1] = fSrcGammaTables[2] = sk_li
near_from_srgb; |
| 442 break; |
| 443 case SkColorSpace::k2Dot2Curve_GammaNamed: |
| 444 fSrcGammaTables[0] = fSrcGammaTables[1] = fSrcGammaTables[2] = sk_li
near_from_2dot2; |
| 445 break; |
| 446 case SkColorSpace::kLinear_GammaNamed: |
| 447 build_table_linear_from_gamma(fSrcGammaTableStorage, 1.0f); |
| 448 fSrcGammaTables[0] = fSrcGammaTables[1] = fSrcGammaTables[2] = fSrcG
ammaTableStorage; |
| 449 break; |
| 450 default: { |
| 451 const SkGammas* gammas = as_CSB(srcSpace)->gammas(); |
| 452 SkASSERT(gammas); |
| 453 |
| 454 for (int i = 0; i < 3; i++) { |
| 455 const SkGammaCurve& curve = (*gammas)[i]; |
| 456 |
| 457 if (i > 0) { |
| 458 // Check if this curve matches the first curve. In this cas
e, we can |
| 459 // share the same table pointer. Logically, this should alm
ost always |
| 460 // be true. I've never seen a profile where all three gamma
curves |
| 461 // didn't match. But it is possible that they won't. |
| 462 // TODO (msarett): |
| 463 // This comparison won't catch the case where each gamma cur
ve has a |
| 464 // pointer to its own look-up table, but the tables actually
match. |
| 465 // Should we perform a deep compare of gamma tables here? O
r should |
| 466 // we catch this when parsing the profile? Or should we not
worry |
| 467 // about a bit of redundant work? |
| 468 if (curve.quickEquals((*gammas)[0])) { |
| 469 fSrcGammaTables[i] = fSrcGammaTables[0]; |
| 470 continue; |
| 471 } |
| 472 } |
| 473 |
| 474 if (curve.isNamed()) { |
| 475 switch (curve.fNamed) { |
| 476 case SkColorSpace::kSRGB_GammaNamed: |
| 477 fSrcGammaTables[i] = sk_linear_from_srgb; |
| 478 break; |
| 479 case SkColorSpace::k2Dot2Curve_GammaNamed: |
| 480 fSrcGammaTables[i] = sk_linear_from_2dot2; |
| 481 break; |
| 482 case SkColorSpace::kLinear_GammaNamed: |
| 483 build_table_linear_from_gamma(&fSrcGammaTableStorage
[i * 256], 1.0f); |
| 484 fSrcGammaTables[i] = &fSrcGammaTableStorage[i * 256]
; |
| 485 break; |
| 486 default: |
| 487 SkASSERT(false); |
| 488 break; |
| 489 } |
| 490 } else if (curve.isValue()) { |
| 491 build_table_linear_from_gamma(&fSrcGammaTableStorage[i * 256
], curve.fValue); |
| 492 fSrcGammaTables[i] = &fSrcGammaTableStorage[i * 256]; |
| 493 } else if (curve.isTable()) { |
| 494 build_table_linear_from_gamma(&fSrcGammaTableStorage[i * 256
], |
| 495 curve.fTable.get(), curve.fTab
leSize); |
| 496 fSrcGammaTables[i] = &fSrcGammaTableStorage[i * 256]; |
| 497 } else { |
| 498 SkASSERT(curve.isParametric()); |
| 499 build_table_linear_from_gamma(&fSrcGammaTableStorage[i * 256
], curve.fG, |
| 500 curve.fA, curve.fB, curve.fC,
curve.fD, curve.fE, |
| 501 curve.fF); |
| 502 fSrcGammaTables[i] = &fSrcGammaTableStorage[i * 256]; |
| 503 } |
| 504 } |
| 505 } |
| 506 } |
| 507 |
| 508 // Build tables to transform linear to dst gamma. |
| 509 switch (dstSpace->gammaNamed()) { |
| 510 case SkColorSpace::kSRGB_GammaNamed: |
| 511 case SkColorSpace::k2Dot2Curve_GammaNamed: |
| 512 break; |
| 513 case SkColorSpace::kLinear_GammaNamed: |
| 514 build_table_linear_to_gamma(fDstGammaTableStorage, kDstGammaTableSiz
e, 1.0f); |
| 515 fDstGammaTables[0] = fDstGammaTables[1] = fDstGammaTables[2] = fDstG
ammaTableStorage; |
| 516 break; |
| 517 default: { |
| 518 const SkGammas* gammas = as_CSB(dstSpace)->gammas(); |
| 519 SkASSERT(gammas); |
| 520 |
| 521 for (int i = 0; i < 3; i++) { |
| 522 const SkGammaCurve& curve = (*gammas)[i]; |
| 523 |
| 524 if (i > 0) { |
| 525 // Check if this curve matches the first curve. In this cas
e, we can |
| 526 // share the same table pointer. Logically, this should alm
ost always |
| 527 // be true. I've never seen a profile where all three gamma
curves |
| 528 // didn't match. But it is possible that they won't. |
| 529 // TODO (msarett): |
| 530 // This comparison won't catch the case where each gamma cur
ve has a |
| 531 // pointer to its own look-up table (but the tables actually
match). |
| 532 // Should we perform a deep compare of gamma tables here? O
r should |
| 533 // we catch this when parsing the profile? Or should we not
worry |
| 534 // about a bit of redundant work? |
| 535 if (curve.quickEquals((*gammas)[0])) { |
| 536 fDstGammaTables[i] = fDstGammaTables[0]; |
| 537 continue; |
| 538 } |
| 539 } |
| 540 |
| 541 if (curve.isNamed()) { |
| 542 switch (curve.fNamed) { |
| 543 case SkColorSpace::kSRGB_GammaNamed: |
| 544 fDstGammaTables[i] = linear_to_srgb; |
| 545 break; |
| 546 case SkColorSpace::k2Dot2Curve_GammaNamed: |
| 547 fDstGammaTables[i] = linear_to_2dot2; |
| 548 break; |
| 549 case SkColorSpace::kLinear_GammaNamed: |
| 550 build_table_linear_to_gamma( |
| 551 &fDstGammaTableStorage[i * kDstGammaTableSiz
e], |
| 552 kDstGammaTableSize, 1.0f); |
| 553 fDstGammaTables[i] = &fDstGammaTableStorage[i * kDst
GammaTableSize]; |
| 554 break; |
| 555 default: |
| 556 SkASSERT(false); |
| 557 break; |
| 558 } |
| 559 } else if (curve.isValue()) { |
| 560 build_table_linear_to_gamma(&fDstGammaTableStorage[i * kDstG
ammaTableSize], |
| 561 kDstGammaTableSize, curve.fValue
); |
| 562 fDstGammaTables[i] = &fDstGammaTableStorage[i * kDstGammaTab
leSize]; |
| 563 } else if (curve.isTable()) { |
| 564 build_table_linear_to_gamma(&fDstGammaTableStorage[i * kDstG
ammaTableSize], |
| 565 kDstGammaTableSize, curve.fTable
.get(), |
| 566 curve.fTableSize); |
| 567 fDstGammaTables[i] = &fDstGammaTableStorage[i * kDstGammaTab
leSize]; |
| 568 } else { |
| 569 SkASSERT(curve.isParametric()); |
| 570 build_table_linear_to_gamma(&fDstGammaTableStorage[i * kDstG
ammaTableSize], |
| 571 kDstGammaTableSize, curve.fG, cu
rve.fA, curve.fB, |
| 572 curve.fC, curve.fD, curve.fE, cu
rve.fF); |
| 573 fDstGammaTables[i] = &fDstGammaTableStorage[i * kDstGammaTab
leSize]; |
| 574 } |
| 575 } |
| 576 } |
| 577 } |
| 578 } |
| 579 |
| 580 template <> |
| 581 void SkFastXform<SkColorSpace::kSRGB_GammaNamed> |
| 582 ::xform_RGB1_8888(uint32_t* dst, const uint32_t* src, uint32_t len) const |
| 583 { |
| 584 SkOpts::color_xform_RGB1_to_srgb(dst, src, len, fSrcGammaTables, fSrcToDst); |
| 585 } |
| 586 |
| 587 template <> |
| 588 void SkFastXform<SkColorSpace::k2Dot2Curve_GammaNamed> |
| 589 ::xform_RGB1_8888(uint32_t* dst, const uint32_t* src, uint32_t len) const |
| 590 { |
| 591 SkOpts::color_xform_RGB1_to_2dot2(dst, src, len, fSrcGammaTables, fSrcToDst)
; |
| 592 } |
| 593 |
| 594 template <> |
| 595 void SkFastXform<SkColorSpace::kNonStandard_GammaNamed> |
| 596 ::xform_RGB1_8888(uint32_t* dst, const uint32_t* src, uint32_t len) const |
| 597 { |
| 598 SkOpts::color_xform_RGB1_to_table(dst, src, len, fSrcGammaTables, fSrcToDst,
fDstGammaTables); |
| 599 } |
| 600 |
| 601 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
| 602 |
476 SkDefaultXform::SkDefaultXform(const sk_sp<SkColorSpace>& srcSpace, const SkMatr
ix44& srcToDst, | 603 SkDefaultXform::SkDefaultXform(const sk_sp<SkColorSpace>& srcSpace, const SkMatr
ix44& srcToDst, |
477 const sk_sp<SkColorSpace>& dstSpace) | 604 const sk_sp<SkColorSpace>& dstSpace) |
478 : fColorLUT(sk_ref_sp((SkColorLookUpTable*) as_CSB(srcSpace)->colorLUT())) | 605 : fColorLUT(sk_ref_sp((SkColorLookUpTable*) as_CSB(srcSpace)->colorLUT())) |
479 , fSrcToDst(srcToDst) | 606 , fSrcToDst(srcToDst) |
480 { | 607 { |
481 // Build tables to transform src gamma to linear. | 608 // Build tables to transform src gamma to linear. |
482 switch (srcSpace->gammaNamed()) { | 609 switch (srcSpace->gammaNamed()) { |
483 case SkColorSpace::kSRGB_GammaNamed: | 610 case SkColorSpace::kSRGB_GammaNamed: |
484 fSrcGammaTables[0] = fSrcGammaTables[1] = fSrcGammaTables[2] = sk_li
near_from_srgb; | 611 fSrcGammaTables[0] = fSrcGammaTables[1] = fSrcGammaTables[2] = sk_li
near_from_srgb; |
485 break; | 612 break; |
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
778 r = fDstGammaTables[0][sk_float_round2int((kDstGammaTableSize - 1) * dst
Floats[0])]; | 905 r = fDstGammaTables[0][sk_float_round2int((kDstGammaTableSize - 1) * dst
Floats[0])]; |
779 g = fDstGammaTables[1][sk_float_round2int((kDstGammaTableSize - 1) * dst
Floats[1])]; | 906 g = fDstGammaTables[1][sk_float_round2int((kDstGammaTableSize - 1) * dst
Floats[1])]; |
780 b = fDstGammaTables[2][sk_float_round2int((kDstGammaTableSize - 1) * dst
Floats[2])]; | 907 b = fDstGammaTables[2][sk_float_round2int((kDstGammaTableSize - 1) * dst
Floats[2])]; |
781 | 908 |
782 *dst = SkPackARGB32NoCheck(0xFF, r, g, b); | 909 *dst = SkPackARGB32NoCheck(0xFF, r, g, b); |
783 | 910 |
784 dst++; | 911 dst++; |
785 src++; | 912 src++; |
786 } | 913 } |
787 } | 914 } |
OLD | NEW |