SkColorSpaceXform.cpp revision ac41bac40f5a80d2bc5ccec584c23478a6900179
19876ac5b3016e5353c072378ac1545a0a2270757msarett/* 29876ac5b3016e5353c072378ac1545a0a2270757msarett * Copyright 2016 Google Inc. 39876ac5b3016e5353c072378ac1545a0a2270757msarett * 49876ac5b3016e5353c072378ac1545a0a2270757msarett * Use of this source code is governed by a BSD-style license that can be 59876ac5b3016e5353c072378ac1545a0a2270757msarett * found in the LICENSE file. 69876ac5b3016e5353c072378ac1545a0a2270757msarett */ 79876ac5b3016e5353c072378ac1545a0a2270757msarett 89876ac5b3016e5353c072378ac1545a0a2270757msarett#include "SkColorPriv.h" 99876ac5b3016e5353c072378ac1545a0a2270757msarett#include "SkColorSpace_Base.h" 109876ac5b3016e5353c072378ac1545a0a2270757msarett#include "SkColorSpaceXform.h" 11a9e878c836994bce695274b4c28890290139dcdfmsarett#include "SkOpts.h" 12ac41bac40f5a80d2bc5ccec584c23478a6900179mtklein#include "SkSRGB.h" 139876ac5b3016e5353c072378ac1545a0a2270757msarett 14dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarettstatic inline bool compute_gamut_xform(SkMatrix44* srcToDst, const SkMatrix44& srcToXYZ, 15dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett const SkMatrix44& dstToXYZ) { 169876ac5b3016e5353c072378ac1545a0a2270757msarett if (!dstToXYZ.invert(srcToDst)) { 179876ac5b3016e5353c072378ac1545a0a2270757msarett return false; 189876ac5b3016e5353c072378ac1545a0a2270757msarett } 199876ac5b3016e5353c072378ac1545a0a2270757msarett 209876ac5b3016e5353c072378ac1545a0a2270757msarett srcToDst->postConcat(srcToXYZ); 219876ac5b3016e5353c072378ac1545a0a2270757msarett return true; 229876ac5b3016e5353c072378ac1545a0a2270757msarett} 239876ac5b3016e5353c072378ac1545a0a2270757msarett 249876ac5b3016e5353c072378ac1545a0a2270757msarettstd::unique_ptr<SkColorSpaceXform> SkColorSpaceXform::New(const sk_sp<SkColorSpace>& srcSpace, 259876ac5b3016e5353c072378ac1545a0a2270757msarett const sk_sp<SkColorSpace>& dstSpace) { 269876ac5b3016e5353c072378ac1545a0a2270757msarett if (!srcSpace || !dstSpace) { 27dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett // Invalid input 289876ac5b3016e5353c072378ac1545a0a2270757msarett return nullptr; 299876ac5b3016e5353c072378ac1545a0a2270757msarett } 309876ac5b3016e5353c072378ac1545a0a2270757msarett 310f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett if (as_CSB(dstSpace)->colorLUT()) { 320f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // It would be really weird for a dst profile to have a color LUT. I don't think 330f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // we need to support this. 34dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett return nullptr; 35dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett } 369876ac5b3016e5353c072378ac1545a0a2270757msarett 37dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett SkMatrix44 srcToDst(SkMatrix44::kUninitialized_Constructor); 38dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett if (!compute_gamut_xform(&srcToDst, srcSpace->xyz(), dstSpace->xyz())) { 39dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett return nullptr; 40dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett } 41dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett 42d2809573deb7b99e764f7f71fe34a5b5322df0b2msarett if (0.0f == srcToDst.getFloat(3, 0) && 43dea0340cadb759932e53416a657f5ea75fee8b5fmsarett 0.0f == srcToDst.getFloat(3, 1) && 440f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 0.0f == srcToDst.getFloat(3, 2) && 450f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett !as_CSB(srcSpace)->colorLUT()) 46a9e878c836994bce695274b4c28890290139dcdfmsarett { 47d2809573deb7b99e764f7f71fe34a5b5322df0b2msarett switch (srcSpace->gammaNamed()) { 48d2809573deb7b99e764f7f71fe34a5b5322df0b2msarett case SkColorSpace::kSRGB_GammaNamed: 49d2809573deb7b99e764f7f71fe34a5b5322df0b2msarett if (SkColorSpace::kSRGB_GammaNamed == dstSpace->gammaNamed()) { 50d2809573deb7b99e764f7f71fe34a5b5322df0b2msarett return std::unique_ptr<SkColorSpaceXform>( 51d2809573deb7b99e764f7f71fe34a5b5322df0b2msarett new SkFastXform<SkColorSpace::kSRGB_GammaNamed, 52d2809573deb7b99e764f7f71fe34a5b5322df0b2msarett SkColorSpace::kSRGB_GammaNamed>(srcToDst)); 53d2809573deb7b99e764f7f71fe34a5b5322df0b2msarett } else if (SkColorSpace::k2Dot2Curve_GammaNamed == dstSpace->gammaNamed()) { 54d2809573deb7b99e764f7f71fe34a5b5322df0b2msarett return std::unique_ptr<SkColorSpaceXform>( 55d2809573deb7b99e764f7f71fe34a5b5322df0b2msarett new SkFastXform<SkColorSpace::kSRGB_GammaNamed, 56d2809573deb7b99e764f7f71fe34a5b5322df0b2msarett SkColorSpace::k2Dot2Curve_GammaNamed>(srcToDst)); 57d2809573deb7b99e764f7f71fe34a5b5322df0b2msarett } 58d2809573deb7b99e764f7f71fe34a5b5322df0b2msarett break; 59d2809573deb7b99e764f7f71fe34a5b5322df0b2msarett case SkColorSpace::k2Dot2Curve_GammaNamed: 60d2809573deb7b99e764f7f71fe34a5b5322df0b2msarett if (SkColorSpace::kSRGB_GammaNamed == dstSpace->gammaNamed()) { 61d2809573deb7b99e764f7f71fe34a5b5322df0b2msarett return std::unique_ptr<SkColorSpaceXform>( 62d2809573deb7b99e764f7f71fe34a5b5322df0b2msarett new SkFastXform<SkColorSpace::k2Dot2Curve_GammaNamed, 63d2809573deb7b99e764f7f71fe34a5b5322df0b2msarett SkColorSpace::kSRGB_GammaNamed>(srcToDst)); 64d2809573deb7b99e764f7f71fe34a5b5322df0b2msarett } else if (SkColorSpace::k2Dot2Curve_GammaNamed == dstSpace->gammaNamed()) { 65d2809573deb7b99e764f7f71fe34a5b5322df0b2msarett return std::unique_ptr<SkColorSpaceXform>( 66d2809573deb7b99e764f7f71fe34a5b5322df0b2msarett new SkFastXform<SkColorSpace::k2Dot2Curve_GammaNamed, 67d2809573deb7b99e764f7f71fe34a5b5322df0b2msarett SkColorSpace::k2Dot2Curve_GammaNamed>(srcToDst)); 68d2809573deb7b99e764f7f71fe34a5b5322df0b2msarett } 69d2809573deb7b99e764f7f71fe34a5b5322df0b2msarett break; 70d2809573deb7b99e764f7f71fe34a5b5322df0b2msarett default: 71d2809573deb7b99e764f7f71fe34a5b5322df0b2msarett break; 72dea0340cadb759932e53416a657f5ea75fee8b5fmsarett } 739876ac5b3016e5353c072378ac1545a0a2270757msarett } 749876ac5b3016e5353c072378ac1545a0a2270757msarett 750f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett return std::unique_ptr<SkColorSpaceXform>(new SkDefaultXform(srcSpace, srcToDst, dstSpace)); 769876ac5b3016e5353c072378ac1545a0a2270757msarett} 779876ac5b3016e5353c072378ac1545a0a2270757msarett 789876ac5b3016e5353c072378ac1545a0a2270757msarett/////////////////////////////////////////////////////////////////////////////////////////////////// 799876ac5b3016e5353c072378ac1545a0a2270757msarett 80dea0340cadb759932e53416a657f5ea75fee8b5fmsarettstatic void build_src_to_dst(float srcToDstArray[12], const SkMatrix44& srcToDstMatrix) { 81dea0340cadb759932e53416a657f5ea75fee8b5fmsarett // Build the following row major matrix: 82a9e878c836994bce695274b4c28890290139dcdfmsarett // rX gX bX 0 83a9e878c836994bce695274b4c28890290139dcdfmsarett // rY gY bY 0 84a9e878c836994bce695274b4c28890290139dcdfmsarett // rZ gZ bZ 0 85dea0340cadb759932e53416a657f5ea75fee8b5fmsarett // Swap R and B if necessary to make sure that we output SkPMColor order. 86dea0340cadb759932e53416a657f5ea75fee8b5fmsarett#ifdef SK_PMCOLOR_IS_BGRA 87dea0340cadb759932e53416a657f5ea75fee8b5fmsarett srcToDstArray[0] = srcToDstMatrix.getFloat(0, 2); 88dea0340cadb759932e53416a657f5ea75fee8b5fmsarett srcToDstArray[1] = srcToDstMatrix.getFloat(0, 1); 89dea0340cadb759932e53416a657f5ea75fee8b5fmsarett srcToDstArray[2] = srcToDstMatrix.getFloat(0, 0); 90dea0340cadb759932e53416a657f5ea75fee8b5fmsarett srcToDstArray[3] = 0.0f; 91dea0340cadb759932e53416a657f5ea75fee8b5fmsarett srcToDstArray[4] = srcToDstMatrix.getFloat(1, 2); 92dea0340cadb759932e53416a657f5ea75fee8b5fmsarett srcToDstArray[5] = srcToDstMatrix.getFloat(1, 1); 93dea0340cadb759932e53416a657f5ea75fee8b5fmsarett srcToDstArray[6] = srcToDstMatrix.getFloat(1, 0); 94dea0340cadb759932e53416a657f5ea75fee8b5fmsarett srcToDstArray[7] = 0.0f; 95dea0340cadb759932e53416a657f5ea75fee8b5fmsarett srcToDstArray[8] = srcToDstMatrix.getFloat(2, 2); 96dea0340cadb759932e53416a657f5ea75fee8b5fmsarett srcToDstArray[9] = srcToDstMatrix.getFloat(2, 1); 97dea0340cadb759932e53416a657f5ea75fee8b5fmsarett srcToDstArray[10] = srcToDstMatrix.getFloat(2, 0); 98dea0340cadb759932e53416a657f5ea75fee8b5fmsarett srcToDstArray[11] = 0.0f; 99dea0340cadb759932e53416a657f5ea75fee8b5fmsarett#else 100dea0340cadb759932e53416a657f5ea75fee8b5fmsarett srcToDstArray[0] = srcToDstMatrix.getFloat(0, 0); 101dea0340cadb759932e53416a657f5ea75fee8b5fmsarett srcToDstArray[1] = srcToDstMatrix.getFloat(0, 1); 102dea0340cadb759932e53416a657f5ea75fee8b5fmsarett srcToDstArray[2] = srcToDstMatrix.getFloat(0, 2); 103dea0340cadb759932e53416a657f5ea75fee8b5fmsarett srcToDstArray[3] = 0.0f; 104dea0340cadb759932e53416a657f5ea75fee8b5fmsarett srcToDstArray[4] = srcToDstMatrix.getFloat(1, 0); 105dea0340cadb759932e53416a657f5ea75fee8b5fmsarett srcToDstArray[5] = srcToDstMatrix.getFloat(1, 1); 106dea0340cadb759932e53416a657f5ea75fee8b5fmsarett srcToDstArray[6] = srcToDstMatrix.getFloat(1, 2); 107dea0340cadb759932e53416a657f5ea75fee8b5fmsarett srcToDstArray[7] = 0.0f; 108dea0340cadb759932e53416a657f5ea75fee8b5fmsarett srcToDstArray[8] = srcToDstMatrix.getFloat(2, 0); 109dea0340cadb759932e53416a657f5ea75fee8b5fmsarett srcToDstArray[9] = srcToDstMatrix.getFloat(2, 1); 110dea0340cadb759932e53416a657f5ea75fee8b5fmsarett srcToDstArray[10] = srcToDstMatrix.getFloat(2, 2); 111dea0340cadb759932e53416a657f5ea75fee8b5fmsarett srcToDstArray[11] = 0.0f; 112dea0340cadb759932e53416a657f5ea75fee8b5fmsarett#endif 113dea0340cadb759932e53416a657f5ea75fee8b5fmsarett} 114dea0340cadb759932e53416a657f5ea75fee8b5fmsarett 115d2809573deb7b99e764f7f71fe34a5b5322df0b2msaretttemplate <SkColorSpace::GammaNamed Src, SkColorSpace::GammaNamed Dst> 116d2809573deb7b99e764f7f71fe34a5b5322df0b2msarettSkFastXform<Src, Dst>::SkFastXform(const SkMatrix44& srcToDst) 117dea0340cadb759932e53416a657f5ea75fee8b5fmsarett{ 118dea0340cadb759932e53416a657f5ea75fee8b5fmsarett build_src_to_dst(fSrcToDst, srcToDst); 119dea0340cadb759932e53416a657f5ea75fee8b5fmsarett} 120dea0340cadb759932e53416a657f5ea75fee8b5fmsarett 121d2809573deb7b99e764f7f71fe34a5b5322df0b2msaretttemplate <> 122d2809573deb7b99e764f7f71fe34a5b5322df0b2msarettvoid SkFastXform<SkColorSpace::kSRGB_GammaNamed, SkColorSpace::kSRGB_GammaNamed> 123d2809573deb7b99e764f7f71fe34a5b5322df0b2msarett::xform_RGB1_8888(uint32_t* dst, const uint32_t* src, uint32_t len) const 124d2809573deb7b99e764f7f71fe34a5b5322df0b2msarett{ 125d2809573deb7b99e764f7f71fe34a5b5322df0b2msarett SkOpts::color_xform_RGB1_srgb_to_srgb(dst, src, len, fSrcToDst); 126dea0340cadb759932e53416a657f5ea75fee8b5fmsarett} 127dea0340cadb759932e53416a657f5ea75fee8b5fmsarett 128d2809573deb7b99e764f7f71fe34a5b5322df0b2msaretttemplate <> 129d2809573deb7b99e764f7f71fe34a5b5322df0b2msarettvoid SkFastXform<SkColorSpace::kSRGB_GammaNamed, SkColorSpace::k2Dot2Curve_GammaNamed> 130d2809573deb7b99e764f7f71fe34a5b5322df0b2msarett::xform_RGB1_8888(uint32_t* dst, const uint32_t* src, uint32_t len) const 131d2809573deb7b99e764f7f71fe34a5b5322df0b2msarett{ 132d2809573deb7b99e764f7f71fe34a5b5322df0b2msarett SkOpts::color_xform_RGB1_srgb_to_2dot2(dst, src, len, fSrcToDst); 133d2809573deb7b99e764f7f71fe34a5b5322df0b2msarett} 134dea0340cadb759932e53416a657f5ea75fee8b5fmsarett 135d2809573deb7b99e764f7f71fe34a5b5322df0b2msaretttemplate <> 136d2809573deb7b99e764f7f71fe34a5b5322df0b2msarettvoid SkFastXform<SkColorSpace::k2Dot2Curve_GammaNamed, SkColorSpace::kSRGB_GammaNamed> 137d2809573deb7b99e764f7f71fe34a5b5322df0b2msarett::xform_RGB1_8888(uint32_t* dst, const uint32_t* src, uint32_t len) const 138dea0340cadb759932e53416a657f5ea75fee8b5fmsarett{ 139d2809573deb7b99e764f7f71fe34a5b5322df0b2msarett SkOpts::color_xform_RGB1_2dot2_to_srgb(dst, src, len, fSrcToDst); 140a9e878c836994bce695274b4c28890290139dcdfmsarett} 141a9e878c836994bce695274b4c28890290139dcdfmsarett 142d2809573deb7b99e764f7f71fe34a5b5322df0b2msaretttemplate <> 143d2809573deb7b99e764f7f71fe34a5b5322df0b2msarettvoid SkFastXform<SkColorSpace::k2Dot2Curve_GammaNamed, SkColorSpace::k2Dot2Curve_GammaNamed> 144d2809573deb7b99e764f7f71fe34a5b5322df0b2msarett::xform_RGB1_8888(uint32_t* dst, const uint32_t* src, uint32_t len) const 145d2809573deb7b99e764f7f71fe34a5b5322df0b2msarett{ 146dea0340cadb759932e53416a657f5ea75fee8b5fmsarett SkOpts::color_xform_RGB1_2dot2_to_2dot2(dst, src, len, fSrcToDst); 147a9e878c836994bce695274b4c28890290139dcdfmsarett} 148a9e878c836994bce695274b4c28890290139dcdfmsarett 149a9e878c836994bce695274b4c28890290139dcdfmsarett/////////////////////////////////////////////////////////////////////////////////////////////////// 150a9e878c836994bce695274b4c28890290139dcdfmsarett 151b39067696ad08a26bbe49b71a71f0546dc42a075msarettextern const float sk_linear_from_2dot2[256] = { 152b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.000000000000000000f, 0.000005077051900662f, 0.000023328004666099f, 0.000056921765712193f, 153b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.000107187362341244f, 0.000175123977503027f, 0.000261543754548491f, 0.000367136269815943f, 154b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.000492503787191433f, 0.000638182842167022f, 0.000804658499513058f, 0.000992374304074325f, 155b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.001201739522438400f, 0.001433134589671860f, 0.001686915316789280f, 0.001963416213396470f, 156b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.002262953160706430f, 0.002585825596234170f, 0.002932318323938360f, 0.003302703032003640f, 157b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.003697239578900130f, 0.004116177093282750f, 0.004559754922526020f, 0.005028203456855540f, 158b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.005521744850239660f, 0.006040593654849810f, 0.006584957382581690f, 0.007155037004573030f, 159b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.007751027397660610f, 0.008373117745148580f, 0.009021491898012130f, 0.009696328701658230f, 160b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.010397802292555300f, 0.011126082368383200f, 0.011881334434813700f, 0.012663720031582100f, 161b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.013473396940142600f, 0.014310519374884100f, 0.015175238159625200f, 0.016067700890886900f, 162b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.016988052089250000f, 0.017936433339950200f, 0.018912983423721500f, 0.019917838438785700f, 163b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.020951131914781100f, 0.022012994919336500f, 0.023103556157921400f, 0.024222942067534200f, 164b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.025371276904734600f, 0.026548682828472900f, 0.027755279978126000f, 0.028991186547107800f, 165b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.030256518852388700f, 0.031551391400226400f, 0.032875916948383800f, 0.034230206565082000f, 166b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.035614369684918800f, 0.037028514161960200f, 0.038472746320194600f, 0.039947171001525600f, 167b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.041451891611462500f, 0.042987010162657100f, 0.044552627316421400f, 0.046148842422351000f, 168b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.047775753556170600f, 0.049433457555908000f, 0.051122050056493400f, 0.052841625522879000f, 169b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.054592277281760300f, 0.056374097551979800f, 0.058187177473685400f, 0.060031607136313200f, 170b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.061907475605455800f, 0.063814870948677200f, 0.065753880260330100f, 0.067724589685424300f, 171b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.069727084442598800f, 0.071761448846239100f, 0.073827766327784600f, 0.075926119456264800f, 172b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.078056589958101900f, 0.080219258736215100f, 0.082414205888459200f, 0.084641510725429500f, 173b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.086901251787660300f, 0.089193506862247800f, 0.091518352998919500f, 0.093875866525577800f, 174b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.096266123063339700f, 0.098689197541094500f, 0.101145164209600000f, 0.103634096655137000f, 175b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.106156067812744000f, 0.108711149979039000f, 0.111299414824660000f, 0.113920933406333000f, 176b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.116575776178572000f, 0.119264013005047000f, 0.121985713169619000f, 0.124740945387051000f, 177b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.127529777813422000f, 0.130352278056244000f, 0.133208513184300000f, 0.136098549737202000f, 178b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.139022453734703000f, 0.141980290685736000f, 0.144972125597231000f, 0.147998022982685000f, 179b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.151058046870511000f, 0.154152260812165000f, 0.157280727890073000f, 0.160443510725344000f, 180b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.163640671485290000f, 0.166872271890766000f, 0.170138373223312000f, 0.173439036332135000f, 181b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.176774321640903000f, 0.180144289154390000f, 0.183548998464951000f, 0.186988508758844000f, 182b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.190462878822409000f, 0.193972167048093000f, 0.197516431440340000f, 0.201095729621346000f, 183b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.204710118836677000f, 0.208359655960767000f, 0.212044397502288000f, 0.215764399609395000f, 184b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.219519718074868000f, 0.223310408341127000f, 0.227136525505149000f, 0.230998124323267000f, 185b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.234895259215880000f, 0.238827984272048000f, 0.242796353254002000f, 0.246800419601550000f, 186b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.250840236436400000f, 0.254915856566385000f, 0.259027332489606000f, 0.263174716398492000f, 187b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.267358060183772000f, 0.271577415438375000f, 0.275832833461245000f, 0.280124365261085000f, 188b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.284452061560024000f, 0.288815972797219000f, 0.293216149132375000f, 0.297652640449211000f, 189b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.302125496358853000f, 0.306634766203158000f, 0.311180499057984000f, 0.315762743736397000f, 190b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.320381548791810000f, 0.325036962521076000f, 0.329729032967515000f, 0.334457807923889000f, 191b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.339223334935327000f, 0.344025661302187000f, 0.348864834082879000f, 0.353740900096629000f, 192b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.358653905926199000f, 0.363603897920553000f, 0.368590922197487000f, 0.373615024646202000f, 193b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.378676250929840000f, 0.383774646487975000f, 0.388910256539059000f, 0.394083126082829000f, 194b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.399293299902674000f, 0.404540822567962000f, 0.409825738436323000f, 0.415148091655907000f, 195b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.420507926167587000f, 0.425905285707146000f, 0.431340213807410000f, 0.436812753800359000f, 196b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.442322948819202000f, 0.447870841800410000f, 0.453456475485731000f, 0.459079892424160000f, 197b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.464741134973889000f, 0.470440245304218000f, 0.476177265397440000f, 0.481952237050698000f, 198b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.487765201877811000f, 0.493616201311074000f, 0.499505276603030000f, 0.505432468828216000f, 199b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.511397818884880000f, 0.517401367496673000f, 0.523443155214325000f, 0.529523222417277000f, 200b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.535641609315311000f, 0.541798355950137000f, 0.547993502196972000f, 0.554227087766085000f, 201b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.560499152204328000f, 0.566809734896638000f, 0.573158875067523000f, 0.579546611782525000f, 202b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.585972983949661000f, 0.592438030320847000f, 0.598941789493296000f, 0.605484299910907000f, 203b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.612065599865624000f, 0.618685727498780000f, 0.625344720802427000f, 0.632042617620641000f, 204b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.638779455650817000f, 0.645555272444935000f, 0.652370105410821000f, 0.659223991813387000f, 205b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.666116968775851000f, 0.673049073280942000f, 0.680020342172095000f, 0.687030812154625000f, 206b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.694080519796882000f, 0.701169501531402000f, 0.708297793656032000f, 0.715465432335048000f, 207b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.722672453600255000f, 0.729918893352071000f, 0.737204787360605000f, 0.744530171266715000f, 208b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.751895080583051000f, 0.759299550695091000f, 0.766743616862161000f, 0.774227314218442000f, 209b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.781750677773962000f, 0.789313742415586000f, 0.796916542907978000f, 0.804559113894567000f, 210b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.812241489898490000f, 0.819963705323528000f, 0.827725794455034000f, 0.835527791460841000f, 211b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.843369730392169000f, 0.851251645184515000f, 0.859173569658532000f, 0.867135537520905000f, 212b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.875137582365205000f, 0.883179737672745000f, 0.891262036813419000f, 0.899384513046529000f, 213b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.907547199521614000f, 0.915750129279253000f, 0.923993335251873000f, 0.932276850264543000f, 214b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.940600707035753000f, 0.948964938178195000f, 0.957369576199527000f, 0.965814653503130000f, 215b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.974300202388861000f, 0.982826255053791000f, 0.991392843592940000f, 1.000000000000000000f, 216b39067696ad08a26bbe49b71a71f0546dc42a075msarett}; 217b39067696ad08a26bbe49b71a71f0546dc42a075msarett 218b39067696ad08a26bbe49b71a71f0546dc42a075msarettstatic void build_table_linear_from_gamma(float* outTable, float exponent) { 219b39067696ad08a26bbe49b71a71f0546dc42a075msarett for (float x = 0.0f; x <= 1.0f; x += (1.0f/255.0f)) { 220b39067696ad08a26bbe49b71a71f0546dc42a075msarett *outTable++ = powf(x, exponent); 221b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 2229876ac5b3016e5353c072378ac1545a0a2270757msarett} 2239876ac5b3016e5353c072378ac1545a0a2270757msarett 224b39067696ad08a26bbe49b71a71f0546dc42a075msarett// Interpolating lookup in a variably sized table. 225b39067696ad08a26bbe49b71a71f0546dc42a075msarettstatic float interp_lut(float input, const float* table, int tableSize) { 226b39067696ad08a26bbe49b71a71f0546dc42a075msarett float index = input * (tableSize - 1); 227b39067696ad08a26bbe49b71a71f0546dc42a075msarett float diff = index - sk_float_floor2int(index); 228b39067696ad08a26bbe49b71a71f0546dc42a075msarett return table[(int) sk_float_floor2int(index)] * (1.0f - diff) + 229b39067696ad08a26bbe49b71a71f0546dc42a075msarett table[(int) sk_float_ceil2int(index)] * diff; 230b39067696ad08a26bbe49b71a71f0546dc42a075msarett} 231b39067696ad08a26bbe49b71a71f0546dc42a075msarett 232b39067696ad08a26bbe49b71a71f0546dc42a075msarett// outTable is always 256 entries, inTable may be larger or smaller. 233b39067696ad08a26bbe49b71a71f0546dc42a075msarettstatic void build_table_linear_from_gamma(float* outTable, const float* inTable, 234b39067696ad08a26bbe49b71a71f0546dc42a075msarett int inTableSize) { 235b39067696ad08a26bbe49b71a71f0546dc42a075msarett if (256 == inTableSize) { 236b39067696ad08a26bbe49b71a71f0546dc42a075msarett memcpy(outTable, inTable, sizeof(float) * 256); 237b39067696ad08a26bbe49b71a71f0546dc42a075msarett return; 238b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 239b39067696ad08a26bbe49b71a71f0546dc42a075msarett 240b39067696ad08a26bbe49b71a71f0546dc42a075msarett for (float x = 0.0f; x <= 1.0f; x += (1.0f/255.0f)) { 241b39067696ad08a26bbe49b71a71f0546dc42a075msarett *outTable++ = interp_lut(x, inTable, inTableSize); 242b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 243b39067696ad08a26bbe49b71a71f0546dc42a075msarett} 244b39067696ad08a26bbe49b71a71f0546dc42a075msarett 245b39067696ad08a26bbe49b71a71f0546dc42a075msarettstatic void build_table_linear_from_gamma(float* outTable, float g, float a, float b, float c, 246b39067696ad08a26bbe49b71a71f0546dc42a075msarett float d, float e, float f) { 247b39067696ad08a26bbe49b71a71f0546dc42a075msarett // Y = (aX + b)^g + c for X >= d 248b39067696ad08a26bbe49b71a71f0546dc42a075msarett // Y = eX + f otherwise 249b39067696ad08a26bbe49b71a71f0546dc42a075msarett for (float x = 0.0f; x <= 1.0f; x += (1.0f/255.0f)) { 250b39067696ad08a26bbe49b71a71f0546dc42a075msarett if (x >= d) { 251b39067696ad08a26bbe49b71a71f0546dc42a075msarett *outTable++ = powf(a * x + b, g) + c; 252b39067696ad08a26bbe49b71a71f0546dc42a075msarett } else { 253b39067696ad08a26bbe49b71a71f0546dc42a075msarett *outTable++ = e * x + f; 254b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 255b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 256b39067696ad08a26bbe49b71a71f0546dc42a075msarett} 257b39067696ad08a26bbe49b71a71f0546dc42a075msarett 258b39067696ad08a26bbe49b71a71f0546dc42a075msarettstatic constexpr uint8_t linear_to_srgb[1024] = { 259b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0, 3, 6, 10, 13, 15, 18, 20, 22, 23, 25, 27, 28, 30, 31, 32, 34, 35, 260b39067696ad08a26bbe49b71a71f0546dc42a075msarett 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 49, 50, 51, 52, 261b39067696ad08a26bbe49b71a71f0546dc42a075msarett 53, 53, 54, 55, 56, 56, 57, 58, 58, 59, 60, 61, 61, 62, 62, 63, 64, 64, 262b39067696ad08a26bbe49b71a71f0546dc42a075msarett 65, 66, 66, 67, 67, 68, 68, 69, 70, 70, 71, 71, 72, 72, 73, 73, 74, 74, 263b39067696ad08a26bbe49b71a71f0546dc42a075msarett 75, 76, 76, 77, 77, 78, 78, 79, 79, 79, 80, 80, 81, 81, 82, 82, 83, 83, 264b39067696ad08a26bbe49b71a71f0546dc42a075msarett 84, 84, 85, 85, 85, 86, 86, 87, 87, 88, 88, 88, 89, 89, 90, 90, 91, 91, 265b39067696ad08a26bbe49b71a71f0546dc42a075msarett 91, 92, 92, 93, 93, 93, 94, 94, 95, 95, 95, 96, 96, 97, 97, 97, 98, 98, 266b39067696ad08a26bbe49b71a71f0546dc42a075msarett 98, 99, 99, 99, 100, 100, 101, 101, 101, 102, 102, 102, 103, 103, 103, 104, 104, 104, 267b39067696ad08a26bbe49b71a71f0546dc42a075msarett 105, 105, 106, 106, 106, 107, 107, 107, 108, 108, 108, 109, 109, 109, 110, 110, 110, 110, 268b39067696ad08a26bbe49b71a71f0546dc42a075msarett 111, 111, 111, 112, 112, 112, 113, 113, 113, 114, 114, 114, 115, 115, 115, 115, 116, 116, 269b39067696ad08a26bbe49b71a71f0546dc42a075msarett 116, 117, 117, 117, 118, 118, 118, 118, 119, 119, 119, 120, 120, 120, 121, 121, 121, 121, 270b39067696ad08a26bbe49b71a71f0546dc42a075msarett 122, 122, 122, 123, 123, 123, 123, 124, 124, 124, 125, 125, 125, 125, 126, 126, 126, 126, 271b39067696ad08a26bbe49b71a71f0546dc42a075msarett 127, 127, 127, 128, 128, 128, 128, 129, 129, 129, 129, 130, 130, 130, 130, 131, 131, 131, 272b39067696ad08a26bbe49b71a71f0546dc42a075msarett 131, 132, 132, 132, 133, 133, 133, 133, 134, 134, 134, 134, 135, 135, 135, 135, 136, 136, 273b39067696ad08a26bbe49b71a71f0546dc42a075msarett 136, 136, 137, 137, 137, 137, 138, 138, 138, 138, 138, 139, 139, 139, 139, 140, 140, 140, 274b39067696ad08a26bbe49b71a71f0546dc42a075msarett 140, 141, 141, 141, 141, 142, 142, 142, 142, 143, 143, 143, 143, 143, 144, 144, 144, 144, 275b39067696ad08a26bbe49b71a71f0546dc42a075msarett 145, 145, 145, 145, 146, 146, 146, 146, 146, 147, 147, 147, 147, 148, 148, 148, 148, 148, 276b39067696ad08a26bbe49b71a71f0546dc42a075msarett 149, 149, 149, 149, 150, 150, 150, 150, 150, 151, 151, 151, 151, 152, 152, 152, 152, 152, 277b39067696ad08a26bbe49b71a71f0546dc42a075msarett 153, 153, 153, 153, 153, 154, 154, 154, 154, 155, 155, 155, 155, 155, 156, 156, 156, 156, 278b39067696ad08a26bbe49b71a71f0546dc42a075msarett 156, 157, 157, 157, 157, 157, 158, 158, 158, 158, 158, 159, 159, 159, 159, 159, 160, 160, 279b39067696ad08a26bbe49b71a71f0546dc42a075msarett 160, 160, 160, 161, 161, 161, 161, 161, 162, 162, 162, 162, 162, 163, 163, 163, 163, 163, 280b39067696ad08a26bbe49b71a71f0546dc42a075msarett 164, 164, 164, 164, 164, 165, 165, 165, 165, 165, 166, 166, 166, 166, 166, 167, 167, 167, 281b39067696ad08a26bbe49b71a71f0546dc42a075msarett 167, 167, 168, 168, 168, 168, 168, 168, 169, 169, 169, 169, 169, 170, 170, 170, 170, 170, 282b39067696ad08a26bbe49b71a71f0546dc42a075msarett 171, 171, 171, 171, 171, 171, 172, 172, 172, 172, 172, 173, 173, 173, 173, 173, 173, 174, 283b39067696ad08a26bbe49b71a71f0546dc42a075msarett 174, 174, 174, 174, 175, 175, 175, 175, 175, 175, 176, 176, 176, 176, 176, 177, 177, 177, 284b39067696ad08a26bbe49b71a71f0546dc42a075msarett 177, 177, 177, 178, 178, 178, 178, 178, 178, 179, 179, 179, 179, 179, 179, 180, 180, 180, 285b39067696ad08a26bbe49b71a71f0546dc42a075msarett 180, 180, 181, 181, 181, 181, 181, 181, 182, 182, 182, 182, 182, 182, 183, 183, 183, 183, 286b39067696ad08a26bbe49b71a71f0546dc42a075msarett 183, 183, 184, 184, 184, 184, 184, 184, 185, 185, 185, 185, 185, 185, 186, 186, 186, 186, 287b39067696ad08a26bbe49b71a71f0546dc42a075msarett 186, 186, 187, 187, 187, 187, 187, 187, 188, 188, 188, 188, 188, 188, 189, 189, 189, 189, 288b39067696ad08a26bbe49b71a71f0546dc42a075msarett 189, 189, 190, 190, 190, 190, 190, 190, 191, 191, 191, 191, 191, 191, 191, 192, 192, 192, 289b39067696ad08a26bbe49b71a71f0546dc42a075msarett 192, 192, 192, 193, 193, 193, 193, 193, 193, 194, 194, 194, 194, 194, 194, 194, 195, 195, 290b39067696ad08a26bbe49b71a71f0546dc42a075msarett 195, 195, 195, 195, 196, 196, 196, 196, 196, 196, 197, 197, 197, 197, 197, 197, 197, 198, 291b39067696ad08a26bbe49b71a71f0546dc42a075msarett 198, 198, 198, 198, 198, 199, 199, 199, 199, 199, 199, 199, 200, 200, 200, 200, 200, 200, 292b39067696ad08a26bbe49b71a71f0546dc42a075msarett 200, 201, 201, 201, 201, 201, 201, 202, 202, 202, 202, 202, 202, 202, 203, 203, 203, 203, 293b39067696ad08a26bbe49b71a71f0546dc42a075msarett 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 205, 205, 205, 205, 205, 205, 206, 206, 294b39067696ad08a26bbe49b71a71f0546dc42a075msarett 206, 206, 206, 206, 206, 207, 207, 207, 207, 207, 207, 207, 208, 208, 208, 208, 208, 208, 295b39067696ad08a26bbe49b71a71f0546dc42a075msarett 208, 209, 209, 209, 209, 209, 209, 209, 210, 210, 210, 210, 210, 210, 210, 211, 211, 211, 296b39067696ad08a26bbe49b71a71f0546dc42a075msarett 211, 211, 211, 211, 212, 212, 212, 212, 212, 212, 212, 212, 213, 213, 213, 213, 213, 213, 297b39067696ad08a26bbe49b71a71f0546dc42a075msarett 213, 214, 214, 214, 214, 214, 214, 214, 215, 215, 215, 215, 215, 215, 215, 216, 216, 216, 298b39067696ad08a26bbe49b71a71f0546dc42a075msarett 216, 216, 216, 216, 216, 217, 217, 217, 217, 217, 217, 217, 218, 218, 218, 218, 218, 218, 299b39067696ad08a26bbe49b71a71f0546dc42a075msarett 218, 219, 219, 219, 219, 219, 219, 219, 219, 220, 220, 220, 220, 220, 220, 220, 221, 221, 300b39067696ad08a26bbe49b71a71f0546dc42a075msarett 221, 221, 221, 221, 221, 221, 222, 222, 222, 222, 222, 222, 222, 222, 223, 223, 223, 223, 301b39067696ad08a26bbe49b71a71f0546dc42a075msarett 223, 223, 223, 224, 224, 224, 224, 224, 224, 224, 224, 225, 225, 225, 225, 225, 225, 225, 302b39067696ad08a26bbe49b71a71f0546dc42a075msarett 225, 226, 226, 226, 226, 226, 226, 226, 227, 227, 227, 227, 227, 227, 227, 227, 228, 228, 303b39067696ad08a26bbe49b71a71f0546dc42a075msarett 228, 228, 228, 228, 228, 228, 229, 229, 229, 229, 229, 229, 229, 229, 230, 230, 230, 230, 304b39067696ad08a26bbe49b71a71f0546dc42a075msarett 230, 230, 230, 230, 231, 231, 231, 231, 231, 231, 231, 231, 232, 232, 232, 232, 232, 232, 305b39067696ad08a26bbe49b71a71f0546dc42a075msarett 232, 232, 233, 233, 233, 233, 233, 233, 233, 233, 234, 234, 234, 234, 234, 234, 234, 234, 306b39067696ad08a26bbe49b71a71f0546dc42a075msarett 235, 235, 235, 235, 235, 235, 235, 235, 236, 236, 236, 236, 236, 236, 236, 236, 236, 237, 307b39067696ad08a26bbe49b71a71f0546dc42a075msarett 237, 237, 237, 237, 237, 237, 237, 238, 238, 238, 238, 238, 238, 238, 238, 239, 239, 239, 308b39067696ad08a26bbe49b71a71f0546dc42a075msarett 239, 239, 239, 239, 239, 239, 240, 240, 240, 240, 240, 240, 240, 240, 241, 241, 241, 241, 309b39067696ad08a26bbe49b71a71f0546dc42a075msarett 241, 241, 241, 241, 241, 242, 242, 242, 242, 242, 242, 242, 242, 243, 243, 243, 243, 243, 310b39067696ad08a26bbe49b71a71f0546dc42a075msarett 243, 243, 243, 243, 244, 244, 244, 244, 244, 244, 244, 244, 245, 245, 245, 245, 245, 245, 311b39067696ad08a26bbe49b71a71f0546dc42a075msarett 245, 245, 245, 246, 246, 246, 246, 246, 246, 246, 246, 246, 247, 247, 247, 247, 247, 247, 312b39067696ad08a26bbe49b71a71f0546dc42a075msarett 247, 247, 248, 248, 248, 248, 248, 248, 248, 248, 248, 249, 249, 249, 249, 249, 249, 249, 313b39067696ad08a26bbe49b71a71f0546dc42a075msarett 249, 249, 250, 250, 250, 250, 250, 250, 250, 250, 250, 251, 251, 251, 251, 251, 251, 251, 314b39067696ad08a26bbe49b71a71f0546dc42a075msarett 251, 251, 252, 252, 252, 252, 252, 252, 252, 252, 252, 253, 253, 253, 253, 253, 253, 253, 315b39067696ad08a26bbe49b71a71f0546dc42a075msarett 253, 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 255, 255, 255, 255, 255 316b39067696ad08a26bbe49b71a71f0546dc42a075msarett}; 317b39067696ad08a26bbe49b71a71f0546dc42a075msarett 318b39067696ad08a26bbe49b71a71f0546dc42a075msarettstatic constexpr uint8_t linear_to_2dot2[1024] = { 319b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0, 11, 15, 18, 21, 23, 25, 26, 28, 30, 31, 32, 34, 35, 36, 37, 39, 40, 320b39067696ad08a26bbe49b71a71f0546dc42a075msarett 41, 42, 43, 44, 45, 45, 46, 47, 48, 49, 50, 50, 51, 52, 53, 54, 54, 55, 321b39067696ad08a26bbe49b71a71f0546dc42a075msarett 56, 56, 57, 58, 58, 59, 60, 60, 61, 62, 62, 63, 63, 64, 65, 65, 66, 66, 322b39067696ad08a26bbe49b71a71f0546dc42a075msarett 67, 68, 68, 69, 69, 70, 70, 71, 71, 72, 72, 73, 73, 74, 74, 75, 75, 76, 323b39067696ad08a26bbe49b71a71f0546dc42a075msarett 76, 77, 77, 78, 78, 79, 79, 80, 80, 81, 81, 81, 82, 82, 83, 83, 84, 84, 324b39067696ad08a26bbe49b71a71f0546dc42a075msarett 84, 85, 85, 86, 86, 87, 87, 87, 88, 88, 89, 89, 89, 90, 90, 91, 91, 91, 325b39067696ad08a26bbe49b71a71f0546dc42a075msarett 92, 92, 93, 93, 93, 94, 94, 94, 95, 95, 96, 96, 96, 97, 97, 97, 98, 98, 326b39067696ad08a26bbe49b71a71f0546dc42a075msarett 98, 99, 99, 99, 100, 100, 101, 101, 101, 102, 102, 102, 103, 103, 103, 104, 104, 104, 327b39067696ad08a26bbe49b71a71f0546dc42a075msarett 105, 105, 105, 106, 106, 106, 107, 107, 107, 108, 108, 108, 108, 109, 109, 109, 110, 110, 328b39067696ad08a26bbe49b71a71f0546dc42a075msarett 110, 111, 111, 111, 112, 112, 112, 112, 113, 113, 113, 114, 114, 114, 115, 115, 115, 115, 329b39067696ad08a26bbe49b71a71f0546dc42a075msarett 116, 116, 116, 117, 117, 117, 117, 118, 118, 118, 119, 119, 119, 119, 120, 120, 120, 121, 330b39067696ad08a26bbe49b71a71f0546dc42a075msarett 121, 121, 121, 122, 122, 122, 123, 123, 123, 123, 124, 124, 124, 124, 125, 125, 125, 125, 331b39067696ad08a26bbe49b71a71f0546dc42a075msarett 126, 126, 126, 127, 127, 127, 127, 128, 128, 128, 128, 129, 129, 129, 129, 130, 130, 130, 332b39067696ad08a26bbe49b71a71f0546dc42a075msarett 130, 131, 131, 131, 131, 132, 132, 132, 132, 133, 133, 133, 133, 134, 134, 134, 134, 135, 333b39067696ad08a26bbe49b71a71f0546dc42a075msarett 135, 135, 135, 136, 136, 136, 136, 137, 137, 137, 137, 138, 138, 138, 138, 138, 139, 139, 334b39067696ad08a26bbe49b71a71f0546dc42a075msarett 139, 139, 140, 140, 140, 140, 141, 141, 141, 141, 142, 142, 142, 142, 142, 143, 143, 143, 335b39067696ad08a26bbe49b71a71f0546dc42a075msarett 143, 144, 144, 144, 144, 144, 145, 145, 145, 145, 146, 146, 146, 146, 146, 147, 147, 147, 336b39067696ad08a26bbe49b71a71f0546dc42a075msarett 147, 148, 148, 148, 148, 148, 149, 149, 149, 149, 149, 150, 150, 150, 150, 151, 151, 151, 337b39067696ad08a26bbe49b71a71f0546dc42a075msarett 151, 151, 152, 152, 152, 152, 152, 153, 153, 153, 153, 154, 154, 154, 154, 154, 155, 155, 338b39067696ad08a26bbe49b71a71f0546dc42a075msarett 155, 155, 155, 156, 156, 156, 156, 156, 157, 157, 157, 157, 157, 158, 158, 158, 158, 158, 339b39067696ad08a26bbe49b71a71f0546dc42a075msarett 159, 159, 159, 159, 159, 160, 160, 160, 160, 160, 161, 161, 161, 161, 161, 162, 162, 162, 340b39067696ad08a26bbe49b71a71f0546dc42a075msarett 162, 162, 163, 163, 163, 163, 163, 164, 164, 164, 164, 164, 165, 165, 165, 165, 165, 165, 341b39067696ad08a26bbe49b71a71f0546dc42a075msarett 166, 166, 166, 166, 166, 167, 167, 167, 167, 167, 168, 168, 168, 168, 168, 168, 169, 169, 342b39067696ad08a26bbe49b71a71f0546dc42a075msarett 169, 169, 169, 170, 170, 170, 170, 170, 171, 171, 171, 171, 171, 171, 172, 172, 172, 172, 343b39067696ad08a26bbe49b71a71f0546dc42a075msarett 172, 173, 173, 173, 173, 173, 173, 174, 174, 174, 174, 174, 174, 175, 175, 175, 175, 175, 344b39067696ad08a26bbe49b71a71f0546dc42a075msarett 176, 176, 176, 176, 176, 176, 177, 177, 177, 177, 177, 177, 178, 178, 178, 178, 178, 179, 345b39067696ad08a26bbe49b71a71f0546dc42a075msarett 179, 179, 179, 179, 179, 180, 180, 180, 180, 180, 180, 181, 181, 181, 181, 181, 181, 182, 346b39067696ad08a26bbe49b71a71f0546dc42a075msarett 182, 182, 182, 182, 182, 183, 183, 183, 183, 183, 183, 184, 184, 184, 184, 184, 185, 185, 347b39067696ad08a26bbe49b71a71f0546dc42a075msarett 185, 185, 185, 185, 186, 186, 186, 186, 186, 186, 186, 187, 187, 187, 187, 187, 187, 188, 348b39067696ad08a26bbe49b71a71f0546dc42a075msarett 188, 188, 188, 188, 188, 189, 189, 189, 189, 189, 189, 190, 190, 190, 190, 190, 190, 191, 349b39067696ad08a26bbe49b71a71f0546dc42a075msarett 191, 191, 191, 191, 191, 192, 192, 192, 192, 192, 192, 192, 193, 193, 193, 193, 193, 193, 350b39067696ad08a26bbe49b71a71f0546dc42a075msarett 194, 194, 194, 194, 194, 194, 195, 195, 195, 195, 195, 195, 195, 196, 196, 196, 196, 196, 351b39067696ad08a26bbe49b71a71f0546dc42a075msarett 196, 197, 197, 197, 197, 197, 197, 197, 198, 198, 198, 198, 198, 198, 199, 199, 199, 199, 352b39067696ad08a26bbe49b71a71f0546dc42a075msarett 199, 199, 199, 200, 200, 200, 200, 200, 200, 201, 201, 201, 201, 201, 201, 201, 202, 202, 353b39067696ad08a26bbe49b71a71f0546dc42a075msarett 202, 202, 202, 202, 202, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 354b39067696ad08a26bbe49b71a71f0546dc42a075msarett 205, 205, 205, 205, 205, 205, 205, 206, 206, 206, 206, 206, 206, 206, 207, 207, 207, 207, 355b39067696ad08a26bbe49b71a71f0546dc42a075msarett 207, 207, 207, 208, 208, 208, 208, 208, 208, 209, 209, 209, 209, 209, 209, 209, 210, 210, 356b39067696ad08a26bbe49b71a71f0546dc42a075msarett 210, 210, 210, 210, 210, 211, 211, 211, 211, 211, 211, 211, 212, 212, 212, 212, 212, 212, 357b39067696ad08a26bbe49b71a71f0546dc42a075msarett 212, 213, 213, 213, 213, 213, 213, 213, 213, 214, 214, 214, 214, 214, 214, 214, 215, 215, 358b39067696ad08a26bbe49b71a71f0546dc42a075msarett 215, 215, 215, 215, 215, 216, 216, 216, 216, 216, 216, 216, 217, 217, 217, 217, 217, 217, 359b39067696ad08a26bbe49b71a71f0546dc42a075msarett 217, 218, 218, 218, 218, 218, 218, 218, 218, 219, 219, 219, 219, 219, 219, 219, 220, 220, 360b39067696ad08a26bbe49b71a71f0546dc42a075msarett 220, 220, 220, 220, 220, 221, 221, 221, 221, 221, 221, 221, 221, 222, 222, 222, 222, 222, 361b39067696ad08a26bbe49b71a71f0546dc42a075msarett 222, 222, 223, 223, 223, 223, 223, 223, 223, 223, 224, 224, 224, 224, 224, 224, 224, 225, 362b39067696ad08a26bbe49b71a71f0546dc42a075msarett 225, 225, 225, 225, 225, 225, 225, 226, 226, 226, 226, 226, 226, 226, 226, 227, 227, 227, 363b39067696ad08a26bbe49b71a71f0546dc42a075msarett 227, 227, 227, 227, 228, 228, 228, 228, 228, 228, 228, 228, 229, 229, 229, 229, 229, 229, 364b39067696ad08a26bbe49b71a71f0546dc42a075msarett 229, 229, 230, 230, 230, 230, 230, 230, 230, 230, 231, 231, 231, 231, 231, 231, 231, 232, 365b39067696ad08a26bbe49b71a71f0546dc42a075msarett 232, 232, 232, 232, 232, 232, 232, 233, 233, 233, 233, 233, 233, 233, 233, 234, 234, 234, 366b39067696ad08a26bbe49b71a71f0546dc42a075msarett 234, 234, 234, 234, 234, 235, 235, 235, 235, 235, 235, 235, 235, 236, 236, 236, 236, 236, 367b39067696ad08a26bbe49b71a71f0546dc42a075msarett 236, 236, 236, 237, 237, 237, 237, 237, 237, 237, 237, 238, 238, 238, 238, 238, 238, 238, 368b39067696ad08a26bbe49b71a71f0546dc42a075msarett 238, 238, 239, 239, 239, 239, 239, 239, 239, 239, 240, 240, 240, 240, 240, 240, 240, 240, 369b39067696ad08a26bbe49b71a71f0546dc42a075msarett 241, 241, 241, 241, 241, 241, 241, 241, 242, 242, 242, 242, 242, 242, 242, 242, 243, 243, 370b39067696ad08a26bbe49b71a71f0546dc42a075msarett 243, 243, 243, 243, 243, 243, 243, 244, 244, 244, 244, 244, 244, 244, 244, 245, 245, 245, 371b39067696ad08a26bbe49b71a71f0546dc42a075msarett 245, 245, 245, 245, 245, 245, 246, 246, 246, 246, 246, 246, 246, 246, 247, 247, 247, 247, 372b39067696ad08a26bbe49b71a71f0546dc42a075msarett 247, 247, 247, 247, 248, 248, 248, 248, 248, 248, 248, 248, 248, 249, 249, 249, 249, 249, 373b39067696ad08a26bbe49b71a71f0546dc42a075msarett 249, 249, 249, 249, 250, 250, 250, 250, 250, 250, 250, 250, 251, 251, 251, 251, 251, 251, 374b39067696ad08a26bbe49b71a71f0546dc42a075msarett 251, 251, 251, 252, 252, 252, 252, 252, 252, 252, 252, 252, 253, 253, 253, 253, 253, 253, 375b39067696ad08a26bbe49b71a71f0546dc42a075msarett 253, 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 255, 255, 255, 255, 255, 376b39067696ad08a26bbe49b71a71f0546dc42a075msarett}; 377b39067696ad08a26bbe49b71a71f0546dc42a075msarett 378a9e878c836994bce695274b4c28890290139dcdfmsarett// Expand range from 0-1 to 0-255, then convert. 379b39067696ad08a26bbe49b71a71f0546dc42a075msarettstatic uint8_t clamp_normalized_float_to_byte(float v) { 380dea0340cadb759932e53416a657f5ea75fee8b5fmsarett // The ordering of the logic is a little strange here in order 381dea0340cadb759932e53416a657f5ea75fee8b5fmsarett // to make sure we convert NaNs to 0. 3829876ac5b3016e5353c072378ac1545a0a2270757msarett v = v * 255.0f; 383a9e878c836994bce695274b4c28890290139dcdfmsarett if (v >= 254.5f) { 3849876ac5b3016e5353c072378ac1545a0a2270757msarett return 255; 385dea0340cadb759932e53416a657f5ea75fee8b5fmsarett } else if (v >= 0.5f) { 3869876ac5b3016e5353c072378ac1545a0a2270757msarett return (uint8_t) (v + 0.5f); 387dea0340cadb759932e53416a657f5ea75fee8b5fmsarett } else { 388dea0340cadb759932e53416a657f5ea75fee8b5fmsarett return 0; 3899876ac5b3016e5353c072378ac1545a0a2270757msarett } 3909876ac5b3016e5353c072378ac1545a0a2270757msarett} 3919876ac5b3016e5353c072378ac1545a0a2270757msarett 392b39067696ad08a26bbe49b71a71f0546dc42a075msarettstatic void build_table_linear_to_gamma(uint8_t* outTable, int outTableSize, float exponent) { 393b39067696ad08a26bbe49b71a71f0546dc42a075msarett float toGammaExp = 1.0f / exponent; 394b39067696ad08a26bbe49b71a71f0546dc42a075msarett 395b39067696ad08a26bbe49b71a71f0546dc42a075msarett for (int i = 0; i < outTableSize; i++) { 396b39067696ad08a26bbe49b71a71f0546dc42a075msarett float x = ((float) i) * (1.0f / ((float) (outTableSize - 1))); 397b39067696ad08a26bbe49b71a71f0546dc42a075msarett outTable[i] = clamp_normalized_float_to_byte(powf(x, toGammaExp)); 398b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 399dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett} 400dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett 401dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett// Inverse table lookup. Ex: what index corresponds to the input value? This will 402dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett// have strange results when the table is non-increasing. But any sane gamma 403dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett// function will be increasing. 404b39067696ad08a26bbe49b71a71f0546dc42a075msarettstatic float inverse_interp_lut(float input, float* table, int tableSize) { 405dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett if (input <= table[0]) { 406dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett return table[0]; 407dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett } else if (input >= table[tableSize - 1]) { 408dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett return 1.0f; 409dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett } 410dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett 411b39067696ad08a26bbe49b71a71f0546dc42a075msarett for (int i = 1; i < tableSize; i++) { 412dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett if (table[i] >= input) { 413dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett // We are guaranteed that input is greater than table[i - 1]. 414dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett float diff = input - table[i - 1]; 415dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett float distance = table[i] - table[i - 1]; 416dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett float index = (i - 1) + diff / distance; 417dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett return index / (tableSize - 1); 418dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett } 419dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett } 420dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett 421dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett // Should be unreachable, since we'll return before the loop if input is 422dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett // larger than the last entry. 423dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett SkASSERT(false); 424dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett return 0.0f; 425dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett} 426dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett 427b39067696ad08a26bbe49b71a71f0546dc42a075msarettstatic void build_table_linear_to_gamma(uint8_t* outTable, int outTableSize, float* inTable, 428b39067696ad08a26bbe49b71a71f0546dc42a075msarett int inTableSize) { 429b39067696ad08a26bbe49b71a71f0546dc42a075msarett for (int i = 0; i < outTableSize; i++) { 430b39067696ad08a26bbe49b71a71f0546dc42a075msarett float x = ((float) i) * (1.0f / ((float) (outTableSize - 1))); 431b39067696ad08a26bbe49b71a71f0546dc42a075msarett float y = inverse_interp_lut(x, inTable, inTableSize); 432b39067696ad08a26bbe49b71a71f0546dc42a075msarett outTable[i] = clamp_normalized_float_to_byte(y); 433b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 434b39067696ad08a26bbe49b71a71f0546dc42a075msarett} 435dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett 436b39067696ad08a26bbe49b71a71f0546dc42a075msarettstatic float inverse_parametric(float x, float g, float a, float b, float c, float d, float e, 437b39067696ad08a26bbe49b71a71f0546dc42a075msarett float f) { 438b39067696ad08a26bbe49b71a71f0546dc42a075msarett // We need to take the inverse of the following piecewise function. 439b39067696ad08a26bbe49b71a71f0546dc42a075msarett // Y = (aX + b)^g + c for X >= d 440b39067696ad08a26bbe49b71a71f0546dc42a075msarett // Y = eX + f otherwise 441b39067696ad08a26bbe49b71a71f0546dc42a075msarett 442b39067696ad08a26bbe49b71a71f0546dc42a075msarett // Assume that the gamma function is continuous, or this won't make much sense anyway. 443b39067696ad08a26bbe49b71a71f0546dc42a075msarett // Plug in |d| to the first equation to calculate the new piecewise interval. 444b39067696ad08a26bbe49b71a71f0546dc42a075msarett // Then simply use the inverse of the original functions. 445b39067696ad08a26bbe49b71a71f0546dc42a075msarett float interval = e * d + f; 446b39067696ad08a26bbe49b71a71f0546dc42a075msarett if (x < interval) { 447b39067696ad08a26bbe49b71a71f0546dc42a075msarett // X = (Y - F) / E 448b39067696ad08a26bbe49b71a71f0546dc42a075msarett if (0.0f == e) { 449b39067696ad08a26bbe49b71a71f0546dc42a075msarett // The gamma curve for this segment is constant, so the inverse is undefined. 450b39067696ad08a26bbe49b71a71f0546dc42a075msarett // Since this is the lower segment, guess zero. 451b39067696ad08a26bbe49b71a71f0546dc42a075msarett return 0.0f; 452b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 453b39067696ad08a26bbe49b71a71f0546dc42a075msarett 454b39067696ad08a26bbe49b71a71f0546dc42a075msarett return (x - f) / e; 455b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 456b39067696ad08a26bbe49b71a71f0546dc42a075msarett 457b39067696ad08a26bbe49b71a71f0546dc42a075msarett // X = ((Y - C)^(1 / G) - B) / A 458b39067696ad08a26bbe49b71a71f0546dc42a075msarett if (0.0f == a || 0.0f == g) { 459b39067696ad08a26bbe49b71a71f0546dc42a075msarett // The gamma curve for this segment is constant, so the inverse is undefined. 460b39067696ad08a26bbe49b71a71f0546dc42a075msarett // Since this is the upper segment, guess one. 461b39067696ad08a26bbe49b71a71f0546dc42a075msarett return 1.0f; 462b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 463b39067696ad08a26bbe49b71a71f0546dc42a075msarett 464b39067696ad08a26bbe49b71a71f0546dc42a075msarett return (powf(x - c, 1.0f / g) - b) / a; 465b39067696ad08a26bbe49b71a71f0546dc42a075msarett} 466b39067696ad08a26bbe49b71a71f0546dc42a075msarett 467b39067696ad08a26bbe49b71a71f0546dc42a075msarettstatic void build_table_linear_to_gamma(uint8_t* outTable, int outTableSize, float g, float a, 468b39067696ad08a26bbe49b71a71f0546dc42a075msarett float b, float c, float d, float e, float f) { 469b39067696ad08a26bbe49b71a71f0546dc42a075msarett for (int i = 0; i < outTableSize; i++) { 470b39067696ad08a26bbe49b71a71f0546dc42a075msarett float x = ((float) i) * (1.0f / ((float) (outTableSize - 1))); 471b39067696ad08a26bbe49b71a71f0546dc42a075msarett float y = inverse_parametric(x, g, a, b, c, d, e, f); 472b39067696ad08a26bbe49b71a71f0546dc42a075msarett outTable[i] = clamp_normalized_float_to_byte(y); 473b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 474b39067696ad08a26bbe49b71a71f0546dc42a075msarett} 475b39067696ad08a26bbe49b71a71f0546dc42a075msarett 476b39067696ad08a26bbe49b71a71f0546dc42a075msarettSkDefaultXform::SkDefaultXform(const sk_sp<SkColorSpace>& srcSpace, const SkMatrix44& srcToDst, 477b39067696ad08a26bbe49b71a71f0546dc42a075msarett const sk_sp<SkColorSpace>& dstSpace) 4780f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett : fColorLUT(sk_ref_sp((SkColorLookUpTable*) as_CSB(srcSpace)->colorLUT())) 4790f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett , fSrcToDst(srcToDst) 480b39067696ad08a26bbe49b71a71f0546dc42a075msarett{ 481b39067696ad08a26bbe49b71a71f0546dc42a075msarett // Build tables to transform src gamma to linear. 482b39067696ad08a26bbe49b71a71f0546dc42a075msarett switch (srcSpace->gammaNamed()) { 483b39067696ad08a26bbe49b71a71f0546dc42a075msarett case SkColorSpace::kSRGB_GammaNamed: 484b39067696ad08a26bbe49b71a71f0546dc42a075msarett fSrcGammaTables[0] = fSrcGammaTables[1] = fSrcGammaTables[2] = sk_linear_from_srgb; 485b39067696ad08a26bbe49b71a71f0546dc42a075msarett break; 486b39067696ad08a26bbe49b71a71f0546dc42a075msarett case SkColorSpace::k2Dot2Curve_GammaNamed: 487b39067696ad08a26bbe49b71a71f0546dc42a075msarett fSrcGammaTables[0] = fSrcGammaTables[1] = fSrcGammaTables[2] = sk_linear_from_2dot2; 488b39067696ad08a26bbe49b71a71f0546dc42a075msarett break; 489b39067696ad08a26bbe49b71a71f0546dc42a075msarett case SkColorSpace::kLinear_GammaNamed: 490b39067696ad08a26bbe49b71a71f0546dc42a075msarett build_table_linear_from_gamma(fSrcGammaTableStorage, 1.0f); 491b39067696ad08a26bbe49b71a71f0546dc42a075msarett fSrcGammaTables[0] = fSrcGammaTables[1] = fSrcGammaTables[2] = fSrcGammaTableStorage; 492b39067696ad08a26bbe49b71a71f0546dc42a075msarett break; 493b39067696ad08a26bbe49b71a71f0546dc42a075msarett default: { 494b39067696ad08a26bbe49b71a71f0546dc42a075msarett const SkGammas* gammas = as_CSB(srcSpace)->gammas(); 495b39067696ad08a26bbe49b71a71f0546dc42a075msarett SkASSERT(gammas); 496b39067696ad08a26bbe49b71a71f0546dc42a075msarett 497b39067696ad08a26bbe49b71a71f0546dc42a075msarett for (int i = 0; i < 3; i++) { 498b39067696ad08a26bbe49b71a71f0546dc42a075msarett const SkGammaCurve& curve = (*gammas)[i]; 499b39067696ad08a26bbe49b71a71f0546dc42a075msarett 500b39067696ad08a26bbe49b71a71f0546dc42a075msarett if (i > 0) { 501b39067696ad08a26bbe49b71a71f0546dc42a075msarett // Check if this curve matches the first curve. In this case, we can 502b39067696ad08a26bbe49b71a71f0546dc42a075msarett // share the same table pointer. Logically, this should almost always 503b39067696ad08a26bbe49b71a71f0546dc42a075msarett // be true. I've never seen a profile where all three gamma curves 504b39067696ad08a26bbe49b71a71f0546dc42a075msarett // didn't match. But it is possible that they won't. 505b39067696ad08a26bbe49b71a71f0546dc42a075msarett // TODO (msarett): 506b39067696ad08a26bbe49b71a71f0546dc42a075msarett // This comparison won't catch the case where each gamma curve has a 507b39067696ad08a26bbe49b71a71f0546dc42a075msarett // pointer to its own look-up table, but the tables actually match. 508b39067696ad08a26bbe49b71a71f0546dc42a075msarett // Should we perform a deep compare of gamma tables here? Or should 509b39067696ad08a26bbe49b71a71f0546dc42a075msarett // we catch this when parsing the profile? Or should we not worry 510b39067696ad08a26bbe49b71a71f0546dc42a075msarett // about a bit of redundant work? 511b39067696ad08a26bbe49b71a71f0546dc42a075msarett if (curve.quickEquals((*gammas)[0])) { 512b39067696ad08a26bbe49b71a71f0546dc42a075msarett fSrcGammaTables[i] = fSrcGammaTables[0]; 513b39067696ad08a26bbe49b71a71f0546dc42a075msarett continue; 514b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 515b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 516b39067696ad08a26bbe49b71a71f0546dc42a075msarett 517b39067696ad08a26bbe49b71a71f0546dc42a075msarett if (curve.isNamed()) { 518b39067696ad08a26bbe49b71a71f0546dc42a075msarett switch (curve.fNamed) { 519b39067696ad08a26bbe49b71a71f0546dc42a075msarett case SkColorSpace::kSRGB_GammaNamed: 520b39067696ad08a26bbe49b71a71f0546dc42a075msarett fSrcGammaTables[i] = sk_linear_from_srgb; 521b39067696ad08a26bbe49b71a71f0546dc42a075msarett break; 522b39067696ad08a26bbe49b71a71f0546dc42a075msarett case SkColorSpace::k2Dot2Curve_GammaNamed: 523b39067696ad08a26bbe49b71a71f0546dc42a075msarett fSrcGammaTables[i] = sk_linear_from_2dot2; 524b39067696ad08a26bbe49b71a71f0546dc42a075msarett break; 525b39067696ad08a26bbe49b71a71f0546dc42a075msarett case SkColorSpace::kLinear_GammaNamed: 526b39067696ad08a26bbe49b71a71f0546dc42a075msarett build_table_linear_from_gamma(&fSrcGammaTableStorage[i * 256], 1.0f); 527b39067696ad08a26bbe49b71a71f0546dc42a075msarett fSrcGammaTables[i] = &fSrcGammaTableStorage[i * 256]; 528b39067696ad08a26bbe49b71a71f0546dc42a075msarett break; 529b39067696ad08a26bbe49b71a71f0546dc42a075msarett default: 530b39067696ad08a26bbe49b71a71f0546dc42a075msarett SkASSERT(false); 531b39067696ad08a26bbe49b71a71f0546dc42a075msarett break; 532b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 533b39067696ad08a26bbe49b71a71f0546dc42a075msarett } else if (curve.isValue()) { 534b39067696ad08a26bbe49b71a71f0546dc42a075msarett build_table_linear_from_gamma(&fSrcGammaTableStorage[i * 256], curve.fValue); 535b39067696ad08a26bbe49b71a71f0546dc42a075msarett fSrcGammaTables[i] = &fSrcGammaTableStorage[i * 256]; 536b39067696ad08a26bbe49b71a71f0546dc42a075msarett } else if (curve.isTable()) { 537b39067696ad08a26bbe49b71a71f0546dc42a075msarett build_table_linear_from_gamma(&fSrcGammaTableStorage[i * 256], 538b39067696ad08a26bbe49b71a71f0546dc42a075msarett curve.fTable.get(), curve.fTableSize); 539b39067696ad08a26bbe49b71a71f0546dc42a075msarett fSrcGammaTables[i] = &fSrcGammaTableStorage[i * 256]; 540dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett } else { 541b39067696ad08a26bbe49b71a71f0546dc42a075msarett SkASSERT(curve.isParametric()); 542b39067696ad08a26bbe49b71a71f0546dc42a075msarett build_table_linear_from_gamma(&fSrcGammaTableStorage[i * 256], curve.fG, 543b39067696ad08a26bbe49b71a71f0546dc42a075msarett curve.fA, curve.fB, curve.fC, curve.fD, curve.fE, 544b39067696ad08a26bbe49b71a71f0546dc42a075msarett curve.fF); 545b39067696ad08a26bbe49b71a71f0546dc42a075msarett fSrcGammaTables[i] = &fSrcGammaTableStorage[i * 256]; 546b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 547b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 548b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 549b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 550b39067696ad08a26bbe49b71a71f0546dc42a075msarett 551b39067696ad08a26bbe49b71a71f0546dc42a075msarett // Build tables to transform linear to dst gamma. 552b39067696ad08a26bbe49b71a71f0546dc42a075msarett switch (dstSpace->gammaNamed()) { 553b39067696ad08a26bbe49b71a71f0546dc42a075msarett case SkColorSpace::kSRGB_GammaNamed: 554b39067696ad08a26bbe49b71a71f0546dc42a075msarett fDstGammaTables[0] = fDstGammaTables[1] = fDstGammaTables[2] = linear_to_srgb; 555b39067696ad08a26bbe49b71a71f0546dc42a075msarett break; 556b39067696ad08a26bbe49b71a71f0546dc42a075msarett case SkColorSpace::k2Dot2Curve_GammaNamed: 557b39067696ad08a26bbe49b71a71f0546dc42a075msarett fDstGammaTables[0] = fDstGammaTables[1] = fDstGammaTables[2] = linear_to_2dot2; 558b39067696ad08a26bbe49b71a71f0546dc42a075msarett break; 559b39067696ad08a26bbe49b71a71f0546dc42a075msarett case SkColorSpace::kLinear_GammaNamed: 560b39067696ad08a26bbe49b71a71f0546dc42a075msarett build_table_linear_to_gamma(fDstGammaTableStorage, kDstGammaTableSize, 1.0f); 561b39067696ad08a26bbe49b71a71f0546dc42a075msarett fDstGammaTables[0] = fDstGammaTables[1] = fDstGammaTables[2] = fDstGammaTableStorage; 562b39067696ad08a26bbe49b71a71f0546dc42a075msarett break; 563b39067696ad08a26bbe49b71a71f0546dc42a075msarett default: { 564b39067696ad08a26bbe49b71a71f0546dc42a075msarett const SkGammas* gammas = as_CSB(dstSpace)->gammas(); 565b39067696ad08a26bbe49b71a71f0546dc42a075msarett SkASSERT(gammas); 566b39067696ad08a26bbe49b71a71f0546dc42a075msarett 567b39067696ad08a26bbe49b71a71f0546dc42a075msarett for (int i = 0; i < 3; i++) { 568b39067696ad08a26bbe49b71a71f0546dc42a075msarett const SkGammaCurve& curve = (*gammas)[i]; 569b39067696ad08a26bbe49b71a71f0546dc42a075msarett 570b39067696ad08a26bbe49b71a71f0546dc42a075msarett if (i > 0) { 571b39067696ad08a26bbe49b71a71f0546dc42a075msarett // Check if this curve matches the first curve. In this case, we can 572b39067696ad08a26bbe49b71a71f0546dc42a075msarett // share the same table pointer. Logically, this should almost always 573b39067696ad08a26bbe49b71a71f0546dc42a075msarett // be true. I've never seen a profile where all three gamma curves 574b39067696ad08a26bbe49b71a71f0546dc42a075msarett // didn't match. But it is possible that they won't. 575b39067696ad08a26bbe49b71a71f0546dc42a075msarett // TODO (msarett): 576b39067696ad08a26bbe49b71a71f0546dc42a075msarett // This comparison won't catch the case where each gamma curve has a 577b39067696ad08a26bbe49b71a71f0546dc42a075msarett // pointer to its own look-up table (but the tables actually match). 578b39067696ad08a26bbe49b71a71f0546dc42a075msarett // Should we perform a deep compare of gamma tables here? Or should 579b39067696ad08a26bbe49b71a71f0546dc42a075msarett // we catch this when parsing the profile? Or should we not worry 580b39067696ad08a26bbe49b71a71f0546dc42a075msarett // about a bit of redundant work? 581b39067696ad08a26bbe49b71a71f0546dc42a075msarett if (curve.quickEquals((*gammas)[0])) { 582b39067696ad08a26bbe49b71a71f0546dc42a075msarett fDstGammaTables[i] = fDstGammaTables[0]; 583b39067696ad08a26bbe49b71a71f0546dc42a075msarett continue; 584b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 585b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 586b39067696ad08a26bbe49b71a71f0546dc42a075msarett 587b39067696ad08a26bbe49b71a71f0546dc42a075msarett if (curve.isNamed()) { 588b39067696ad08a26bbe49b71a71f0546dc42a075msarett switch (curve.fNamed) { 589b39067696ad08a26bbe49b71a71f0546dc42a075msarett case SkColorSpace::kSRGB_GammaNamed: 590b39067696ad08a26bbe49b71a71f0546dc42a075msarett fDstGammaTables[i] = linear_to_srgb; 591b39067696ad08a26bbe49b71a71f0546dc42a075msarett break; 592b39067696ad08a26bbe49b71a71f0546dc42a075msarett case SkColorSpace::k2Dot2Curve_GammaNamed: 593b39067696ad08a26bbe49b71a71f0546dc42a075msarett fDstGammaTables[i] = linear_to_2dot2; 594b39067696ad08a26bbe49b71a71f0546dc42a075msarett break; 595b39067696ad08a26bbe49b71a71f0546dc42a075msarett case SkColorSpace::kLinear_GammaNamed: 596b39067696ad08a26bbe49b71a71f0546dc42a075msarett build_table_linear_to_gamma( 597b39067696ad08a26bbe49b71a71f0546dc42a075msarett &fDstGammaTableStorage[i * kDstGammaTableSize], 598b39067696ad08a26bbe49b71a71f0546dc42a075msarett kDstGammaTableSize, 1.0f); 599b39067696ad08a26bbe49b71a71f0546dc42a075msarett fDstGammaTables[i] = &fDstGammaTableStorage[i * kDstGammaTableSize]; 600b39067696ad08a26bbe49b71a71f0546dc42a075msarett break; 601b39067696ad08a26bbe49b71a71f0546dc42a075msarett default: 602b39067696ad08a26bbe49b71a71f0546dc42a075msarett SkASSERT(false); 603b39067696ad08a26bbe49b71a71f0546dc42a075msarett break; 604c4ce6b592487305de251bbebaf8eeee38371b877msarett } 605b39067696ad08a26bbe49b71a71f0546dc42a075msarett } else if (curve.isValue()) { 606b39067696ad08a26bbe49b71a71f0546dc42a075msarett build_table_linear_to_gamma(&fDstGammaTableStorage[i * kDstGammaTableSize], 607b39067696ad08a26bbe49b71a71f0546dc42a075msarett kDstGammaTableSize, curve.fValue); 608b39067696ad08a26bbe49b71a71f0546dc42a075msarett fDstGammaTables[i] = &fDstGammaTableStorage[i * kDstGammaTableSize]; 609b39067696ad08a26bbe49b71a71f0546dc42a075msarett } else if (curve.isTable()) { 610b39067696ad08a26bbe49b71a71f0546dc42a075msarett build_table_linear_to_gamma(&fDstGammaTableStorage[i * kDstGammaTableSize], 611b39067696ad08a26bbe49b71a71f0546dc42a075msarett kDstGammaTableSize, curve.fTable.get(), 612b39067696ad08a26bbe49b71a71f0546dc42a075msarett curve.fTableSize); 613b39067696ad08a26bbe49b71a71f0546dc42a075msarett fDstGammaTables[i] = &fDstGammaTableStorage[i * kDstGammaTableSize]; 614b39067696ad08a26bbe49b71a71f0546dc42a075msarett } else { 615b39067696ad08a26bbe49b71a71f0546dc42a075msarett SkASSERT(curve.isParametric()); 616b39067696ad08a26bbe49b71a71f0546dc42a075msarett build_table_linear_to_gamma(&fDstGammaTableStorage[i * kDstGammaTableSize], 617b39067696ad08a26bbe49b71a71f0546dc42a075msarett kDstGammaTableSize, curve.fG, curve.fA, curve.fB, 618b39067696ad08a26bbe49b71a71f0546dc42a075msarett curve.fC, curve.fD, curve.fE, curve.fF); 619b39067696ad08a26bbe49b71a71f0546dc42a075msarett fDstGammaTables[i] = &fDstGammaTableStorage[i * kDstGammaTableSize]; 620dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett } 621dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett } 622dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett } 623b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 624b39067696ad08a26bbe49b71a71f0546dc42a075msarett} 625b39067696ad08a26bbe49b71a71f0546dc42a075msarett 6260f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarettstatic float byte_to_float(uint8_t byte) { 6270f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett return ((float) byte) * (1.0f / 255.0f); 6280f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett} 6290f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 630b39067696ad08a26bbe49b71a71f0546dc42a075msarett// Clamp to the 0-1 range. 631b39067696ad08a26bbe49b71a71f0546dc42a075msarettstatic float clamp_normalized_float(float v) { 632b39067696ad08a26bbe49b71a71f0546dc42a075msarett if (v > 1.0f) { 633b39067696ad08a26bbe49b71a71f0546dc42a075msarett return 1.0f; 634b39067696ad08a26bbe49b71a71f0546dc42a075msarett } else if ((v < 0.0f) || (v != v)) { 635b39067696ad08a26bbe49b71a71f0546dc42a075msarett return 0.0f; 636b39067696ad08a26bbe49b71a71f0546dc42a075msarett } else { 637b39067696ad08a26bbe49b71a71f0546dc42a075msarett return v; 638b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 639b39067696ad08a26bbe49b71a71f0546dc42a075msarett} 640b39067696ad08a26bbe49b71a71f0546dc42a075msarett 6410f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarettstatic void interp_3d_clut(float dst[3], float src[3], const SkColorLookUpTable* colorLUT) { 6420f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // Call the src components x, y, and z. 6430f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett uint8_t maxX = colorLUT->fGridPoints[0] - 1; 6440f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett uint8_t maxY = colorLUT->fGridPoints[1] - 1; 6450f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett uint8_t maxZ = colorLUT->fGridPoints[2] - 1; 6460f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 6470f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // An approximate index into each of the three dimensions of the table. 6480f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett float x = src[0] * maxX; 6490f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett float y = src[1] * maxY; 6500f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett float z = src[2] * maxZ; 6510f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 6520f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // This gives us the low index for our interpolation. 6530f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett int ix = sk_float_floor2int(x); 6540f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett int iy = sk_float_floor2int(y); 6550f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett int iz = sk_float_floor2int(z); 6560f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 6570f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // Make sure the low index is not also the max index. 6580f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett ix = (maxX == ix) ? ix - 1 : ix; 6590f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett iy = (maxY == iy) ? iy - 1 : iy; 6600f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett iz = (maxZ == iz) ? iz - 1 : iz; 6610f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 6620f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // Weighting factors for the interpolation. 6630f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett float diffX = x - ix; 6640f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett float diffY = y - iy; 6650f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett float diffZ = z - iz; 6660f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 6670f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // Constants to help us navigate the 3D table. 6680f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // Ex: Assume x = a, y = b, z = c. 6690f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // table[a * n001 + b * n010 + c * n100] logically equals table[a][b][c]. 6700f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett const int n000 = 0; 6710f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett const int n001 = 3 * colorLUT->fGridPoints[1] * colorLUT->fGridPoints[2]; 6720f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett const int n010 = 3 * colorLUT->fGridPoints[2]; 6730f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett const int n011 = n001 + n010; 6740f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett const int n100 = 3; 6750f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett const int n101 = n100 + n001; 6760f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett const int n110 = n100 + n010; 6770f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett const int n111 = n110 + n001; 6780f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 6790f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // Base ptr into the table. 6800f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett float* ptr = &colorLUT->fTable[ix*n001 + iy*n010 + iz*n100]; 6810f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 6820f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // The code below performs a tetrahedral interpolation for each of the three 6830f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // dst components. Once the tetrahedron containing the interpolation point is 6840f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // identified, the interpolation is a weighted sum of grid values at the 6850f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // vertices of the tetrahedron. The claim is that tetrahedral interpolation 6860f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // provides a more accurate color conversion. 6870f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // blogs.mathworks.com/steve/2006/11/24/tetrahedral-interpolation-for-colorspace-conversion/ 6880f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // 6890f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // I have one test image, and visually I can't tell the difference between 6900f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // tetrahedral and trilinear interpolation. In terms of computation, the 6910f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // tetrahedral code requires more branches but less computation. The 6920f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // SampleICC library provides an option for the client to choose either 6930f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // tetrahedral or trilinear. 6940f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett for (int i = 0; i < 3; i++) { 6950f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett if (diffZ < diffY) { 6960f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett if (diffZ < diffX) { 6970f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett dst[i] = (ptr[n000] + diffZ * (ptr[n110] - ptr[n010]) + 6980f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett diffY * (ptr[n010] - ptr[n000]) + 6990f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett diffX * (ptr[n111] - ptr[n110])); 7000f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett } else if (diffY < diffX) { 7010f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett dst[i] = (ptr[n000] + diffZ * (ptr[n111] - ptr[n011]) + 7020f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett diffY * (ptr[n011] - ptr[n001]) + 7030f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett diffX * (ptr[n001] - ptr[n000])); 7040f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett } else { 7050f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett dst[i] = (ptr[n000] + diffZ * (ptr[n111] - ptr[n011]) + 7060f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett diffY * (ptr[n010] - ptr[n000]) + 7070f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett diffX * (ptr[n011] - ptr[n010])); 7080f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett } 7090f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett } else { 7100f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett if (diffZ < diffX) { 7110f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett dst[i] = (ptr[n000] + diffZ * (ptr[n101] - ptr[n001]) + 7120f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett diffY * (ptr[n111] - ptr[n101]) + 7130f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett diffX * (ptr[n001] - ptr[n000])); 7140f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett } else if (diffY < diffX) { 7150f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett dst[i] = (ptr[n000] + diffZ * (ptr[n100] - ptr[n000]) + 7160f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett diffY * (ptr[n111] - ptr[n101]) + 7170f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett diffX * (ptr[n101] - ptr[n100])); 7180f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett } else { 7190f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett dst[i] = (ptr[n000] + diffZ * (ptr[n100] - ptr[n000]) + 7200f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett diffY * (ptr[n110] - ptr[n100]) + 7210f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett diffX * (ptr[n111] - ptr[n110])); 7220f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett } 7230f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett } 7240f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 7250f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // Increment the table ptr in order to handle the next component. 7260f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // Note that this is the how table is designed: all of nXXX 7270f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // variables are multiples of 3 because there are 3 output 7280f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // components. 7290f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett ptr++; 7300f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett } 7310f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett} 7320f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 733b39067696ad08a26bbe49b71a71f0546dc42a075msarettvoid SkDefaultXform::xform_RGB1_8888(uint32_t* dst, const uint32_t* src, uint32_t len) const { 734b39067696ad08a26bbe49b71a71f0546dc42a075msarett while (len-- > 0) { 7350f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett uint8_t r = (*src >> 0) & 0xFF, 7360f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett g = (*src >> 8) & 0xFF, 7370f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett b = (*src >> 16) & 0xFF; 7380f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 7390f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett if (fColorLUT) { 7400f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett float in[3]; 7410f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett float out[3]; 7420f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 7430f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett in[0] = byte_to_float(r); 7440f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett in[1] = byte_to_float(g); 7450f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett in[2] = byte_to_float(b); 7460f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 7470f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett interp_3d_clut(out, in, fColorLUT.get()); 7480f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 7490f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett r = sk_float_round2int(255.0f * clamp_normalized_float(out[0])); 7500f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett g = sk_float_round2int(255.0f * clamp_normalized_float(out[1])); 7510f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett b = sk_float_round2int(255.0f * clamp_normalized_float(out[2])); 7520f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett } 7530f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 754b39067696ad08a26bbe49b71a71f0546dc42a075msarett // Convert to linear. 755b39067696ad08a26bbe49b71a71f0546dc42a075msarett float srcFloats[3]; 7560f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett srcFloats[0] = fSrcGammaTables[0][r]; 7570f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett srcFloats[1] = fSrcGammaTables[1][g]; 7580f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett srcFloats[2] = fSrcGammaTables[2][b]; 759dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett 760dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett // Convert to dst gamut. 761dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett float dstFloats[3]; 762dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett dstFloats[0] = srcFloats[0] * fSrcToDst.getFloat(0, 0) + 763dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett srcFloats[1] * fSrcToDst.getFloat(1, 0) + 764dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett srcFloats[2] * fSrcToDst.getFloat(2, 0) + fSrcToDst.getFloat(3, 0); 765dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett dstFloats[1] = srcFloats[0] * fSrcToDst.getFloat(0, 1) + 766dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett srcFloats[1] * fSrcToDst.getFloat(1, 1) + 767dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett srcFloats[2] * fSrcToDst.getFloat(2, 1) + fSrcToDst.getFloat(3, 1); 768dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett dstFloats[2] = srcFloats[0] * fSrcToDst.getFloat(0, 2) + 769dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett srcFloats[1] * fSrcToDst.getFloat(1, 2) + 770dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett srcFloats[2] * fSrcToDst.getFloat(2, 2) + fSrcToDst.getFloat(3, 2); 771dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett 772b39067696ad08a26bbe49b71a71f0546dc42a075msarett // Clamp to 0-1. 773b39067696ad08a26bbe49b71a71f0546dc42a075msarett dstFloats[0] = clamp_normalized_float(dstFloats[0]); 774b39067696ad08a26bbe49b71a71f0546dc42a075msarett dstFloats[1] = clamp_normalized_float(dstFloats[1]); 775b39067696ad08a26bbe49b71a71f0546dc42a075msarett dstFloats[2] = clamp_normalized_float(dstFloats[2]); 776b39067696ad08a26bbe49b71a71f0546dc42a075msarett 777dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett // Convert to dst gamma. 7780f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett r = fDstGammaTables[0][sk_float_round2int((kDstGammaTableSize - 1) * dstFloats[0])]; 7790f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett g = fDstGammaTables[1][sk_float_round2int((kDstGammaTableSize - 1) * dstFloats[1])]; 7800f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett b = fDstGammaTables[2][sk_float_round2int((kDstGammaTableSize - 1) * dstFloats[2])]; 781dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett 782b39067696ad08a26bbe49b71a71f0546dc42a075msarett *dst = SkPackARGB32NoCheck(0xFF, r, g, b); 783dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett 784dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett dst++; 785dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett src++; 786dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett } 787dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett} 788