diff options
author | commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-10-07 18:00:17 +0000 |
---|---|---|
committer | commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-10-07 18:00:17 +0000 |
commit | 6c1ee2d4e727357451c8a6fcf4a08e75890b5d6d (patch) | |
tree | 144de7ce27c8400a39866d0f53f7be49aa935cda /src/effects | |
parent | dd6cde5235d5d36607f4f1df66057d807b432b99 (diff) |
Luminance-to-alpha color filter (SkLumaColorFilter).
Adding a color filter luma implementation. The plan is to convert
existing clients and then deprecate SkLumaXfermode.
R=bsalomon@google.com, reed@google.com, robertphillips@google.com
Author: fmalita@chromium.org
Review URL: https://codereview.chromium.org/25453004
git-svn-id: http://skia.googlecode.com/svn/trunk@11636 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/effects')
-rw-r--r-- | src/effects/SkLumaColorFilter.cpp | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/src/effects/SkLumaColorFilter.cpp b/src/effects/SkLumaColorFilter.cpp new file mode 100644 index 0000000000..c9f1fb02c3 --- /dev/null +++ b/src/effects/SkLumaColorFilter.cpp @@ -0,0 +1,152 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkLumaColorFilter.h" + +#include "SkColorPriv.h" +#include "SkString.h" +#include "SkUnPreMultiply.h" + +#if SK_SUPPORT_GPU +#include "gl/GrGLEffect.h" +#include "GrContext.h" +#include "GrTBackendEffectFactory.h" +#endif + +void SkLumaColorFilter::filterSpan(const SkPMColor src[], int count, + SkPMColor dst[]) const { + const SkUnPreMultiply::Scale* table = SkUnPreMultiply::GetScaleTable(); + + for (int i = 0; i < count; ++i) { + SkPMColor c = src[i]; + + unsigned r = SkGetPackedR32(c); + unsigned g = SkGetPackedG32(c); + unsigned b = SkGetPackedB32(c); + unsigned a = SkGetPackedA32(c); + + // No need to do anything for white (luminance == 1.0) + if (a != r || a != g || a != b) { + /* + * To avoid un-premultiplying multiple components, we can start + * with the luminance computed in PM space: + * + * Lum = i * (r / a) + j * (g / a) + k * (b / a) + * Lum = (i * r + j * g + k * b) / a + * Lum = Lum'(PM) / a + * + * Then the filter function is: + * + * C' = [ Lum * a, Lum * r, Lum * g, Lum * b ] + * + * which is equivalent to: + * + * C' = [ Lum'(PM), Lum * r, Lum * g, Lum * b ] + */ + unsigned pm_lum = SkComputeLuminance(r, g, b); + unsigned lum = SkUnPreMultiply::ApplyScale(table[a], pm_lum); + + c = SkPackARGB32(pm_lum, + SkMulDiv255Round(r, lum), + SkMulDiv255Round(g, lum), + SkMulDiv255Round(b, lum)); + } + + dst[i] = c; + } +} + +SkColorFilter* SkLumaColorFilter::Create() { + return SkNEW(SkLumaColorFilter); +} + +SkLumaColorFilter::SkLumaColorFilter() + : INHERITED() { +} + +SkLumaColorFilter::SkLumaColorFilter(SkFlattenableReadBuffer& buffer) + : INHERITED(buffer) { +} + +void SkLumaColorFilter::flatten(SkFlattenableWriteBuffer&) const { +} + +#ifdef SK_DEVELOPER +void SkLumaColorFilter::toString(SkString* str) const { + str->append("SkLumaColorFilter "); +} +#endif + +#if SK_SUPPORT_GPU +class LumaColorFilterEffect : public GrEffect { +public: + static GrEffectRef* Create() { + AutoEffectUnref effect(SkNEW(LumaColorFilterEffect)); + return CreateEffectRef(effect); + } + + static const char* Name() { return "Luminance-to-Alpha"; } + + virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { + return GrTBackendEffectFactory<LumaColorFilterEffect>::getInstance(); + } + + virtual void getConstantColorComponents(GrColor* color, + uint32_t* validFlags) const SK_OVERRIDE { + *validFlags = 0; + } + + class GLEffect : public GrGLEffect { + public: + GLEffect(const GrBackendEffectFactory& factory, + const GrDrawEffect&) + : INHERITED(factory) { + } + + static EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&) { + // this class always generates the same code. + return 0; + } + + virtual void emitCode(GrGLShaderBuilder* builder, + const GrDrawEffect&, + EffectKey, + const char* outputColor, + const char* inputColor, + const TransformedCoordsArray&, + const TextureSamplerArray&) SK_OVERRIDE { + if (NULL == inputColor) { + inputColor = GrGLSLOnesVecf(4); + } + + // The max() is to guard against 0 / 0 during unpremul when the incoming color is + // transparent black. + builder->fsCodeAppendf("\tfloat nonZeroAlpha = max(%s.a, 0.00001);\n", inputColor); + builder->fsCodeAppendf("\tfloat luma = dot(vec3(%f, %f, %f), %s.rgb);\n", + SK_ITU_BT709_LUM_COEFF_R, + SK_ITU_BT709_LUM_COEFF_G, + SK_ITU_BT709_LUM_COEFF_B, + inputColor); + builder->fsCodeAppendf("\t%s = vec4(%s.rgb * luma / nonZeroAlpha, luma);\n", + outputColor, inputColor); + + } + + private: + typedef GrGLEffect INHERITED; + }; + +private: + virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE { + return true; + } +}; + +GrEffectRef* SkLumaColorFilter::asNewEffect(GrContext*) const { + return LumaColorFilterEffect::Create(); +} +#endif |