blob: 874dd476f485148bc59515657e414bf739c7cf39 [file] [log] [blame]
/*
* Copyright 2017 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "include/core/SkString.h"
#include "include/effects/SkHighContrastFilter.h"
#include "include/effects/SkRuntimeEffect.h"
#include "include/private/SkTPin.h"
#include "src/core/SkRuntimeEffectPriv.h"
sk_sp<SkColorFilter> SkHighContrastFilter::Make(const SkHighContrastConfig& userConfig) {
if (!userConfig.isValid()) {
return nullptr;
}
// A contrast setting of exactly +1 would divide by zero (1+c)/(1-c), so pull in to +1-ε.
// I'm not exactly sure why we've historically pinned -1 up to -1+ε, maybe just symmetry?
SkHighContrastConfig config = userConfig;
config.fContrast = SkTPin(config.fContrast,
-1.0f + FLT_EPSILON,
+1.0f - FLT_EPSILON);
struct { float M; } uniforms;
SkString code{
"uniform shader input;"
"uniform half M;"
};
code += kRGB_to_HSL_sksl;
code += kHSL_to_RGB_sksl;
code += "half4 main() {";
if (true) {
code += "half4 c = sample(input);"; // c is linear unpremul RGBA in the dst gamut.
}
if (config.fGrayscale) {
code += "c.rgb = dot(half3(0.2126, 0.7152, 0.0722), c.rgb).rrr;";
}
if (config.fInvertStyle == SkHighContrastConfig::InvertStyle::kInvertBrightness) {
code += "c.rgb = 1 - c.rgb;";
}
if (config.fInvertStyle == SkHighContrastConfig::InvertStyle::kInvertLightness) {
code += "c.rgb = rgb_to_hsl(c.rgb);";
code += "c.b = 1 - c.b;";
code += "c.rgb = hsl_to_rgb(c.rgb);";
}
if (float c = config.fContrast) {
uniforms.M = (1+c)/(1-c);
code += "c.rgb = (c.rgb - 0.5)*M + 0.5;";
}
if (true) {
code += "return saturate(c);";
}
code += "}";
auto [effect, err] = SkRuntimeEffect::Make(code);
if (!err.isEmpty()) {
SkDebugf("%s\n%s\n", code.c_str(), err.c_str());
}
SkASSERT(effect && err.isEmpty());
sk_sp<SkColorFilter> input = nullptr;
skcms_TransferFunction linear = SkNamedTransferFn::kLinear;
SkAlphaType unpremul = kUnpremul_SkAlphaType;
return SkColorFilters::WithWorkingFormat(
effect->makeColorFilter(SkData::MakeWithCopy(&uniforms,sizeof(uniforms)), &input, 1),
&linear, nullptr/*use dst gamut*/, &unpremul);
}