SkLumaColorFilter.cpp revision 824c346b6e0e114063c1a8ad4ba7c3a669ee2cff
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright 2013 Google Inc. 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Use of this source code is governed by a BSD-style license that can be 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * found in the LICENSE file. 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkLumaColorFilter.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkColorPriv.h" 117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "SkString.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkUnPreMultiply.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#if SK_SUPPORT_GPU 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "gl/GrGLEffect.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "GrContext.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "GrTBackendEffectFactory.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SkLumaColorFilter::filterSpan(const SkPMColor src[], int count, 21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SkPMColor dst[]) const { 22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const SkUnPreMultiply::Scale* table = SkUnPreMultiply::GetScaleTable(); 23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (int i = 0; i < count; ++i) { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkPMColor c = src[i]; 26eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned r = SkGetPackedR32(c); 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned g = SkGetPackedG32(c); 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned b = SkGetPackedB32(c); 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned a = SkGetPackedA32(c); 317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // No need to do anything for white (luminance == 1.0) 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (a != r || a != g || a != b) { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * To avoid un-premultiplying multiple components, we can start 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * with the luminance computed in PM space: 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * Lum = i * (r / a) + j * (g / a) + k * (b / a) 3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * Lum = (i * r + j * g + k * b) / a 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Lum = Lum'(PM) / a 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Then the filter function is: 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * C' = [ Lum * a, Lum * r, Lum * g, Lum * b ] 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * which is equivalent to: 4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * 487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch * C' = [ Lum'(PM), Lum * r, Lum * g, Lum * b ] 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned pm_lum = SkComputeLuminance(r, g, b); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned lum = SkUnPreMultiply::ApplyScale(table[a], pm_lum); 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 53a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) c = SkPackARGB32(pm_lum, 54a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) SkMulDiv255Round(r, lum), 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SkMulDiv255Round(g, lum), 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkMulDiv255Round(b, lum)); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dst[i] = c; 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SkColorFilter* SkLumaColorFilter::Create() { 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SkNEW(SkLumaColorFilter); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SkLumaColorFilter::SkLumaColorFilter() 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : INHERITED() { 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SkLumaColorFilter::SkLumaColorFilter(SkFlattenableReadBuffer& buffer) 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : INHERITED(buffer) { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void SkLumaColorFilter::flatten(SkFlattenableWriteBuffer&) const { 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SK_DEVELOPER 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SkLumaColorFilter::toString(SkString* str) const { 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) str->append("SkLumaColorFilter "); 81a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SK_SUPPORT_GPU 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class LumaColorFilterEffect : public GrEffect { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public: 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static GrEffectRef* Create() { 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AutoEffectUnref effect(SkNEW(LumaColorFilterEffect)); 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return CreateEffectRef(effect); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char* Name() { return "Luminance-to-Alpha"; } 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GrTBackendEffectFactory<LumaColorFilterEffect>::getInstance(); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 97ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void getConstantColorComponents(GrColor* color, 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32_t* validFlags) const SK_OVERRIDE { 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *validFlags = 0; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 102ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) class GLEffect : public GrGLEffect { 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GLEffect(const GrBackendEffectFactory& factory, 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GrDrawEffect&) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : INHERITED(factory) { 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&) { 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // this class always generates the same code. 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void emitCode(GrGLShaderBuilder* builder, 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GrDrawEffect&, 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EffectKey, 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* outputColor, 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* inputColor, 1207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const TransformedCoordsArray&, 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const TextureSamplerArray&) SK_OVERRIDE { 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (NULL == inputColor) { 123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch inputColor = "vec4(1)"; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The max() is to guard against 0 / 0 during unpremul when the incoming color is 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // transparent black. 128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) builder->fsCodeAppendf("\tfloat nonZeroAlpha = max(%s.a, 0.00001);\n", inputColor); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) builder->fsCodeAppendf("\tfloat luma = dot(vec3(%f, %f, %f), %s.rgb);\n", 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SK_ITU_BT709_LUM_COEFF_R, 131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SK_ITU_BT709_LUM_COEFF_G, 132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SK_ITU_BT709_LUM_COEFF_B, 133a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) inputColor); 134ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch builder->fsCodeAppendf("\t%s = vec4(%s.rgb * luma / nonZeroAlpha, luma);\n", 135ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch outputColor, inputColor); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private: 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef GrGLEffect INHERITED; 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)private: 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE { 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GrEffectRef* SkLumaColorFilter::asNewEffect(GrContext*) const { 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LumaColorFilterEffect::Create(); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)