| 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" |
| (...skipping 19 matching lines...) Expand all Loading... |
| 30 if (as_CSB(srcSpace)->colorLUT() || as_CSB(dstSpace)->colorLUT()) { | 30 if (as_CSB(srcSpace)->colorLUT() || as_CSB(dstSpace)->colorLUT()) { |
| 31 // Unimplemented | 31 // Unimplemented |
| 32 return nullptr; | 32 return nullptr; |
| 33 } | 33 } |
| 34 | 34 |
| 35 SkMatrix44 srcToDst(SkMatrix44::kUninitialized_Constructor); | 35 SkMatrix44 srcToDst(SkMatrix44::kUninitialized_Constructor); |
| 36 if (!compute_gamut_xform(&srcToDst, srcSpace->xyz(), dstSpace->xyz())) { | 36 if (!compute_gamut_xform(&srcToDst, srcSpace->xyz(), dstSpace->xyz())) { |
| 37 return nullptr; | 37 return nullptr; |
| 38 } | 38 } |
| 39 | 39 |
| 40 if (SkColorSpace::k2Dot2Curve_GammaNamed == srcSpace->gammaNamed() && | 40 if (SkColorSpace::k2Dot2Curve_GammaNamed == dstSpace->gammaNamed() && |
| 41 SkColorSpace::k2Dot2Curve_GammaNamed == dstSpace->gammaNamed()) | 41 0.0f == srcToDst.getFloat(3, 0) && |
| 42 0.0f == srcToDst.getFloat(3, 1) && |
| 43 0.0f == srcToDst.getFloat(3, 2)) |
| 42 { | 44 { |
| 43 return std::unique_ptr<SkColorSpaceXform>(new Sk2Dot2Xform(srcToDst)); | 45 if (SkColorSpace::kSRGB_GammaNamed == srcSpace->gammaNamed()) { |
| 46 return std::unique_ptr<SkColorSpaceXform>(new SkSRGBTo2Dot2Xform(src
ToDst)); |
| 47 } else if (SkColorSpace::k2Dot2Curve_GammaNamed == srcSpace->gammaNamed(
)) { |
| 48 return std::unique_ptr<SkColorSpaceXform>(new Sk2Dot2To2Dot2Xform(sr
cToDst)); |
| 49 } |
| 44 } | 50 } |
| 45 | 51 |
| 46 return std::unique_ptr<SkColorSpaceXform>( | 52 return std::unique_ptr<SkColorSpaceXform>( |
| 47 new SkDefaultXform(as_CSB(srcSpace)->gammas(), srcToDst, as_CSB(dstS
pace)->gammas())); | 53 new SkDefaultXform(as_CSB(srcSpace)->gammas(), srcToDst, as_CSB(dstS
pace)->gammas())); |
| 48 } | 54 } |
| 49 | 55 |
| 50 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | 56 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
| 51 | 57 |
| 52 Sk2Dot2Xform::Sk2Dot2Xform(const SkMatrix44& srcToDst) | 58 static void build_src_to_dst(float srcToDstArray[12], const SkMatrix44& srcToDst
Matrix) { |
| 53 { | 59 // Build the following row major matrix: |
| 54 // Build row major 4x4 matrix: | |
| 55 // rX gX bX 0 | 60 // rX gX bX 0 |
| 56 // rY gY bY 0 | 61 // rY gY bY 0 |
| 57 // rZ gZ bZ 0 | 62 // rZ gZ bZ 0 |
| 58 // rQ gQ bQ 0 | 63 // Swap R and B if necessary to make sure that we output SkPMColor order. |
| 59 fSrcToDst[0] = srcToDst.getFloat(0, 0); | 64 #ifdef SK_PMCOLOR_IS_BGRA |
| 60 fSrcToDst[1] = srcToDst.getFloat(0, 1); | 65 srcToDstArray[0] = srcToDstMatrix.getFloat(0, 2); |
| 61 fSrcToDst[2] = srcToDst.getFloat(0, 2); | 66 srcToDstArray[1] = srcToDstMatrix.getFloat(0, 1); |
| 62 fSrcToDst[3] = 0.0f; | 67 srcToDstArray[2] = srcToDstMatrix.getFloat(0, 0); |
| 63 fSrcToDst[4] = srcToDst.getFloat(1, 0); | 68 srcToDstArray[3] = 0.0f; |
| 64 fSrcToDst[5] = srcToDst.getFloat(1, 1); | 69 srcToDstArray[4] = srcToDstMatrix.getFloat(1, 2); |
| 65 fSrcToDst[6] = srcToDst.getFloat(1, 2); | 70 srcToDstArray[5] = srcToDstMatrix.getFloat(1, 1); |
| 66 fSrcToDst[7] = 0.0f; | 71 srcToDstArray[6] = srcToDstMatrix.getFloat(1, 0); |
| 67 fSrcToDst[8] = srcToDst.getFloat(2, 0); | 72 srcToDstArray[7] = 0.0f; |
| 68 fSrcToDst[9] = srcToDst.getFloat(2, 1); | 73 srcToDstArray[8] = srcToDstMatrix.getFloat(2, 2); |
| 69 fSrcToDst[10] = srcToDst.getFloat(2, 2); | 74 srcToDstArray[9] = srcToDstMatrix.getFloat(2, 1); |
| 70 fSrcToDst[11] = 0.0f; | 75 srcToDstArray[10] = srcToDstMatrix.getFloat(2, 0); |
| 71 fSrcToDst[12] = srcToDst.getFloat(3, 0); | 76 srcToDstArray[11] = 0.0f; |
| 72 fSrcToDst[13] = srcToDst.getFloat(3, 1); | 77 #else |
| 73 fSrcToDst[14] = srcToDst.getFloat(3, 2); | 78 srcToDstArray[0] = srcToDstMatrix.getFloat(0, 0); |
| 74 fSrcToDst[15] = 0.0f; | 79 srcToDstArray[1] = srcToDstMatrix.getFloat(0, 1); |
| 80 srcToDstArray[2] = srcToDstMatrix.getFloat(0, 2); |
| 81 srcToDstArray[3] = 0.0f; |
| 82 srcToDstArray[4] = srcToDstMatrix.getFloat(1, 0); |
| 83 srcToDstArray[5] = srcToDstMatrix.getFloat(1, 1); |
| 84 srcToDstArray[6] = srcToDstMatrix.getFloat(1, 2); |
| 85 srcToDstArray[7] = 0.0f; |
| 86 srcToDstArray[8] = srcToDstMatrix.getFloat(2, 0); |
| 87 srcToDstArray[9] = srcToDstMatrix.getFloat(2, 1); |
| 88 srcToDstArray[10] = srcToDstMatrix.getFloat(2, 2); |
| 89 srcToDstArray[11] = 0.0f; |
| 90 #endif |
| 75 } | 91 } |
| 76 | 92 |
| 77 void Sk2Dot2Xform::xform_RGBA_8888(uint32_t* dst, const uint32_t* src, uint32_t
len) const { | 93 SkSRGBTo2Dot2Xform::SkSRGBTo2Dot2Xform(const SkMatrix44& srcToDst) |
| 78 SkOpts::color_xform_2Dot2_RGBA_to_8888(dst, src, len, fSrcToDst); | 94 { |
| 95 build_src_to_dst(fSrcToDst, srcToDst); |
| 96 } |
| 97 |
| 98 void SkSRGBTo2Dot2Xform::xform_RGB1_8888(uint32_t* dst, const uint32_t* src, uin
t32_t len) const { |
| 99 SkOpts::color_xform_RGB1_srgb_to_2dot2(dst, src, len, fSrcToDst); |
| 79 } | 100 } |
| 80 | 101 |
| 81 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | 102 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
| 103 |
| 104 Sk2Dot2To2Dot2Xform::Sk2Dot2To2Dot2Xform(const SkMatrix44& srcToDst) |
| 105 { |
| 106 build_src_to_dst(fSrcToDst, srcToDst); |
| 107 } |
| 108 |
| 109 void Sk2Dot2To2Dot2Xform::xform_RGB1_8888(uint32_t* dst, const uint32_t* src, ui
nt32_t len) const { |
| 110 SkOpts::color_xform_RGB1_2dot2_to_2dot2(dst, src, len, fSrcToDst); |
| 111 } |
| 112 |
| 113 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
| 82 | 114 |
| 83 static inline float byte_to_float(uint8_t v) { | 115 static inline float byte_to_float(uint8_t v) { |
| 84 return ((float) v) * (1.0f / 255.0f); | 116 return ((float) v) * (1.0f / 255.0f); |
| 85 } | 117 } |
| 86 | 118 |
| 87 // Expand range from 0-1 to 0-255, then convert. | 119 // Expand range from 0-1 to 0-255, then convert. |
| 88 static inline uint8_t clamp_normalized_float_to_byte(float v) { | 120 static inline uint8_t clamp_normalized_float_to_byte(float v) { |
| 121 // The ordering of the logic is a little strange here in order |
| 122 // to make sure we convert NaNs to 0. |
| 89 v = v * 255.0f; | 123 v = v * 255.0f; |
| 90 if (v >= 254.5f) { | 124 if (v >= 254.5f) { |
| 91 return 255; | 125 return 255; |
| 92 } else if (v < 0.5f) { | 126 } else if (v >= 0.5f) { |
| 127 return (uint8_t) (v + 0.5f); |
| 128 } else { |
| 93 return 0; | 129 return 0; |
| 94 } else { | |
| 95 return (uint8_t) (v + 0.5f); | |
| 96 } | 130 } |
| 97 } | 131 } |
| 98 | 132 |
| 99 // Interpolating lookup in a variably sized table. | 133 // Interpolating lookup in a variably sized table. |
| 100 static inline float interp_lut(uint8_t byte, float* table, size_t tableSize) { | 134 static inline float interp_lut(uint8_t byte, float* table, size_t tableSize) { |
| 101 float index = byte_to_float(byte) * (tableSize - 1); | 135 float index = byte_to_float(byte) * (tableSize - 1); |
| 102 float diff = index - sk_float_floor2int(index); | 136 float diff = index - sk_float_floor2int(index); |
| 103 return table[(int) sk_float_floor2int(index)] * (1.0f - diff) + | 137 return table[(int) sk_float_floor2int(index)] * (1.0f - diff) + |
| 104 table[(int) sk_float_ceil2int(index)] * diff; | 138 table[(int) sk_float_ceil2int(index)] * diff; |
| 105 } | 139 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 135 return 0.0f; | 169 return 0.0f; |
| 136 } | 170 } |
| 137 | 171 |
| 138 SkDefaultXform::SkDefaultXform(const sk_sp<SkGammas>& srcGammas, const SkMatrix4
4& srcToDst, | 172 SkDefaultXform::SkDefaultXform(const sk_sp<SkGammas>& srcGammas, const SkMatrix4
4& srcToDst, |
| 139 const sk_sp<SkGammas>& dstGammas) | 173 const sk_sp<SkGammas>& dstGammas) |
| 140 : fSrcGammas(srcGammas) | 174 : fSrcGammas(srcGammas) |
| 141 , fSrcToDst(srcToDst) | 175 , fSrcToDst(srcToDst) |
| 142 , fDstGammas(dstGammas) | 176 , fDstGammas(dstGammas) |
| 143 {} | 177 {} |
| 144 | 178 |
| 145 void SkDefaultXform::xform_RGBA_8888(uint32_t* dst, const uint32_t* src, uint32_
t len) const { | 179 void SkDefaultXform::xform_RGB1_8888(uint32_t* dst, const uint32_t* src, uint32_
t len) const { |
| 146 while (len-- > 0) { | 180 while (len-- > 0) { |
| 147 // Convert to linear. | 181 // Convert to linear. |
| 148 // FIXME (msarett): | 182 // FIXME (msarett): |
| 149 // Rather than support three different strategies of transforming gamma,
QCMS | 183 // Rather than support three different strategies of transforming gamma,
QCMS |
| 150 // builds a 256 entry float lookup table from the gamma info. This hand
les | 184 // builds a 256 entry float lookup table from the gamma info. This hand
les |
| 151 // the gamma transform and the conversion from bytes to floats. This ma
y | 185 // the gamma transform and the conversion from bytes to floats. This ma
y |
| 152 // be simpler and faster than our current approach. | 186 // be simpler and faster than our current approach. |
| 153 float srcFloats[3]; | 187 float srcFloats[3]; |
| 154 for (int i = 0; i < 3; i++) { | 188 for (int i = 0; i < 3; i++) { |
| 155 const SkGammaCurve& gamma = (*fSrcGammas)[i]; | 189 const SkGammaCurve& gamma = (*fSrcGammas)[i]; |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 236 | 270 |
| 237 *dst = SkPackARGB32NoCheck(((*src >> 24) & 0xFF), | 271 *dst = SkPackARGB32NoCheck(((*src >> 24) & 0xFF), |
| 238 clamp_normalized_float_to_byte(dstFloats[0]), | 272 clamp_normalized_float_to_byte(dstFloats[0]), |
| 239 clamp_normalized_float_to_byte(dstFloats[1]), | 273 clamp_normalized_float_to_byte(dstFloats[1]), |
| 240 clamp_normalized_float_to_byte(dstFloats[2]))
; | 274 clamp_normalized_float_to_byte(dstFloats[2]))
; |
| 241 | 275 |
| 242 dst++; | 276 dst++; |
| 243 src++; | 277 src++; |
| 244 } | 278 } |
| 245 } | 279 } |
| OLD | NEW |