Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
SkMaskGamma.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2012 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
9
14
15#include <cmath>
16
18 SkScalar toLuma(SkScalar SkDEBUGCODE(gamma), SkScalar luminance) const override {
19 SkASSERT(SK_Scalar1 == gamma);
20 return luminance;
21 }
22 SkScalar fromLuma(SkScalar SkDEBUGCODE(gamma), SkScalar luma) const override {
23 SkASSERT(SK_Scalar1 == gamma);
24 return luma;
25 }
26};
27
29 SkScalar toLuma(SkScalar gamma, SkScalar luminance) const override {
30 return SkScalarPow(luminance, gamma);
31 }
32 SkScalar fromLuma(SkScalar gamma, SkScalar luma) const override {
33 return SkScalarPow(luma, SkScalarInvert(gamma));
34 }
35};
36
38 SkScalar toLuma(SkScalar SkDEBUGCODE(gamma), SkScalar luminance) const override {
39 SkASSERT(0 == gamma);
40 //The magic numbers are derived from the sRGB specification.
41 //See http://www.color.org/chardata/rgb/srgb.xalter .
42 if (luminance <= 0.04045f) {
43 return luminance / 12.92f;
44 }
45 return SkScalarPow((luminance + 0.055f) / 1.055f,
46 2.4f);
47 }
48 SkScalar fromLuma(SkScalar SkDEBUGCODE(gamma), SkScalar luma) const override {
49 SkASSERT(0 == gamma);
50 //The magic numbers are derived from the sRGB specification.
51 //See http://www.color.org/chardata/rgb/srgb.xalter .
52 if (luma <= 0.0031308f) {
53 return luma * 12.92f;
54 }
55 return 1.055f * SkScalarPow(luma, SkScalarInvert(2.4f))
56 - 0.055f;
57 }
58};
59
61 static SkLinearColorSpaceLuminance gSkLinearColorSpaceLuminance;
62 static SkGammaColorSpaceLuminance gSkGammaColorSpaceLuminance;
63 static SkSRGBColorSpaceLuminance gSkSRGBColorSpaceLuminance;
64
65 if (0 == gamma) {
66 return gSkSRGBColorSpaceLuminance;
67 } else if (SK_Scalar1 == gamma) {
68 return gSkLinearColorSpaceLuminance;
69 } else {
70 return gSkGammaColorSpaceLuminance;
71 }
72}
73
74static float apply_contrast(float srca, float contrast) {
75 return srca + ((1.0f - srca) * contrast * srca);
76}
77
78void SkTMaskGamma_build_correcting_lut(uint8_t table[256], U8CPU srcI, SkScalar contrast,
79 const SkColorSpaceLuminance& srcConvert, SkScalar srcGamma,
80 const SkColorSpaceLuminance& dstConvert, SkScalar dstGamma) {
81 const float src = (float)srcI / 255.0f;
82 const float linSrc = srcConvert.toLuma(srcGamma, src);
83 //Guess at the dst. The perceptual inverse provides smaller visual
84 //discontinuities when slight changes to desaturated colors cause a channel
85 //to map to a different correcting lut with neighboring srcI.
86 //See https://code.google.com/p/chromium/issues/detail?id=141425#c59 .
87 const float dst = 1.0f - src;
88 const float linDst = dstConvert.toLuma(dstGamma, dst);
89
90 //Contrast value tapers off to 0 as the src luminance becomes white
91 const float adjustedContrast = contrast * linDst;
92
93 //Remove discontinuity and instability when src is close to dst.
94 //The value 1/256 is arbitrary and appears to contain the instability.
95 if (fabs(src - dst) < (1.0f / 256.0f)) {
96 float ii = 0.0f;
97 for (int i = 0; i < 256; ++i, ii += 1.0f) {
98 float rawSrca = ii / 255.0f;
99 float srca = apply_contrast(rawSrca, adjustedContrast);
100 table[i] = SkToU8(sk_float_round2int(255.0f * srca));
101 }
102 } else {
103 // Avoid slow int to float conversion.
104 float ii = 0.0f;
105 for (int i = 0; i < 256; ++i, ii += 1.0f) {
106 // 'rawSrca += 1.0f / 255.0f' and even
107 // 'rawSrca = i * (1.0f / 255.0f)' can add up to more than 1.0f.
108 // When this happens the table[255] == 0x0 instead of 0xff.
109 // See http://code.google.com/p/chromium/issues/detail?id=146466
110 float rawSrca = ii / 255.0f;
111 float srca = apply_contrast(rawSrca, adjustedContrast);
112 SkASSERT(srca <= 1.0f);
113 float dsta = 1.0f - srca;
114
115 //Calculate the output we want.
116 float linOut = (linSrc * srca + dsta * linDst);
117 SkASSERT(linOut <= 1.0f);
118 float out = dstConvert.fromLuma(dstGamma, linOut);
119
120 //Undo what the blit blend will do.
121 float result = (out - dst) / (src - dst);
122 SkASSERT(sk_float_round2int(255.0f * result) <= 255);
123
124 table[i] = SkToU8(sk_float_round2int(255.0f * result));
125 }
126 }
127}
#define SkASSERT(cond)
Definition SkAssert.h:116
unsigned U8CPU
Definition SkCPUTypes.h:18
#define SkDEBUGCODE(...)
Definition SkDebug.h:23
#define sk_float_round2int(x)
void SkTMaskGamma_build_correcting_lut(uint8_t table[256], U8CPU srcI, SkScalar contrast, const SkColorSpaceLuminance &srcConvert, SkScalar srcGamma, const SkColorSpaceLuminance &dstConvert, SkScalar dstGamma)
static float apply_contrast(float srca, float contrast)
#define SkScalarInvert(x)
Definition SkScalar.h:73
#define SK_Scalar1
Definition SkScalar.h:18
#define SkScalarPow(b, e)
Definition SkScalar.h:43
constexpr uint8_t SkToU8(S x)
Definition SkTo.h:22
SI F table(const skcms_Curve *curve, F v)
virtual SkScalar fromLuma(SkScalar gamma, SkScalar luma) const =0
virtual SkScalar toLuma(SkScalar gamma, SkScalar luminance) const =0
static const SkColorSpaceLuminance & Fetch(SkScalar gamma)
SkScalar fromLuma(SkScalar gamma, SkScalar luma) const override
SkScalar toLuma(SkScalar gamma, SkScalar luminance) const override
SkScalar toLuma(SkScalar SkDEBUGCODE(gamma), SkScalar luminance) const override
SkScalar fromLuma(SkScalar SkDEBUGCODE(gamma), SkScalar luma) const override
SkScalar fromLuma(SkScalar SkDEBUGCODE(gamma), SkScalar luma) const override
SkScalar toLuma(SkScalar SkDEBUGCODE(gamma), SkScalar luminance) const override
float SkScalar
Definition extension.cpp:12
GAsyncResult * result