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

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

Issue 2060823003: Implement fast, correct gamma conversion for color xforms (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Win test Created 4 years, 6 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/SkColorSpaceXform.h ('k') | src/core/SkOpts.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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 }
OLDNEW
« no previous file with comments | « src/core/SkColorSpaceXform.h ('k') | src/core/SkOpts.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698