| 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 |