SkColorSpaceXform.cpp revision 1b93bd1e6eba3d14593490e4e24a34546638c8da
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 146006f678e78af7b6f67a454cd4bc213048983f9dmsarettstatic constexpr float sk_linear_from_2dot2[256] = { 15b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.000000000000000000f, 0.000005077051900662f, 0.000023328004666099f, 0.000056921765712193f, 16b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.000107187362341244f, 0.000175123977503027f, 0.000261543754548491f, 0.000367136269815943f, 17b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.000492503787191433f, 0.000638182842167022f, 0.000804658499513058f, 0.000992374304074325f, 18b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.001201739522438400f, 0.001433134589671860f, 0.001686915316789280f, 0.001963416213396470f, 19b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.002262953160706430f, 0.002585825596234170f, 0.002932318323938360f, 0.003302703032003640f, 20b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.003697239578900130f, 0.004116177093282750f, 0.004559754922526020f, 0.005028203456855540f, 21b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.005521744850239660f, 0.006040593654849810f, 0.006584957382581690f, 0.007155037004573030f, 22b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.007751027397660610f, 0.008373117745148580f, 0.009021491898012130f, 0.009696328701658230f, 23b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.010397802292555300f, 0.011126082368383200f, 0.011881334434813700f, 0.012663720031582100f, 24b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.013473396940142600f, 0.014310519374884100f, 0.015175238159625200f, 0.016067700890886900f, 25b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.016988052089250000f, 0.017936433339950200f, 0.018912983423721500f, 0.019917838438785700f, 26b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.020951131914781100f, 0.022012994919336500f, 0.023103556157921400f, 0.024222942067534200f, 27b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.025371276904734600f, 0.026548682828472900f, 0.027755279978126000f, 0.028991186547107800f, 28b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.030256518852388700f, 0.031551391400226400f, 0.032875916948383800f, 0.034230206565082000f, 29b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.035614369684918800f, 0.037028514161960200f, 0.038472746320194600f, 0.039947171001525600f, 30b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.041451891611462500f, 0.042987010162657100f, 0.044552627316421400f, 0.046148842422351000f, 31b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.047775753556170600f, 0.049433457555908000f, 0.051122050056493400f, 0.052841625522879000f, 32b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.054592277281760300f, 0.056374097551979800f, 0.058187177473685400f, 0.060031607136313200f, 33b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.061907475605455800f, 0.063814870948677200f, 0.065753880260330100f, 0.067724589685424300f, 34b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.069727084442598800f, 0.071761448846239100f, 0.073827766327784600f, 0.075926119456264800f, 35b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.078056589958101900f, 0.080219258736215100f, 0.082414205888459200f, 0.084641510725429500f, 36b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.086901251787660300f, 0.089193506862247800f, 0.091518352998919500f, 0.093875866525577800f, 37b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.096266123063339700f, 0.098689197541094500f, 0.101145164209600000f, 0.103634096655137000f, 38b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.106156067812744000f, 0.108711149979039000f, 0.111299414824660000f, 0.113920933406333000f, 39b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.116575776178572000f, 0.119264013005047000f, 0.121985713169619000f, 0.124740945387051000f, 40b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.127529777813422000f, 0.130352278056244000f, 0.133208513184300000f, 0.136098549737202000f, 41b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.139022453734703000f, 0.141980290685736000f, 0.144972125597231000f, 0.147998022982685000f, 42b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.151058046870511000f, 0.154152260812165000f, 0.157280727890073000f, 0.160443510725344000f, 43b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.163640671485290000f, 0.166872271890766000f, 0.170138373223312000f, 0.173439036332135000f, 44b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.176774321640903000f, 0.180144289154390000f, 0.183548998464951000f, 0.186988508758844000f, 45b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.190462878822409000f, 0.193972167048093000f, 0.197516431440340000f, 0.201095729621346000f, 46b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.204710118836677000f, 0.208359655960767000f, 0.212044397502288000f, 0.215764399609395000f, 47b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.219519718074868000f, 0.223310408341127000f, 0.227136525505149000f, 0.230998124323267000f, 48b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.234895259215880000f, 0.238827984272048000f, 0.242796353254002000f, 0.246800419601550000f, 49b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.250840236436400000f, 0.254915856566385000f, 0.259027332489606000f, 0.263174716398492000f, 50b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.267358060183772000f, 0.271577415438375000f, 0.275832833461245000f, 0.280124365261085000f, 51b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.284452061560024000f, 0.288815972797219000f, 0.293216149132375000f, 0.297652640449211000f, 52b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.302125496358853000f, 0.306634766203158000f, 0.311180499057984000f, 0.315762743736397000f, 53b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.320381548791810000f, 0.325036962521076000f, 0.329729032967515000f, 0.334457807923889000f, 54b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.339223334935327000f, 0.344025661302187000f, 0.348864834082879000f, 0.353740900096629000f, 55b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.358653905926199000f, 0.363603897920553000f, 0.368590922197487000f, 0.373615024646202000f, 56b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.378676250929840000f, 0.383774646487975000f, 0.388910256539059000f, 0.394083126082829000f, 57b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.399293299902674000f, 0.404540822567962000f, 0.409825738436323000f, 0.415148091655907000f, 58b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.420507926167587000f, 0.425905285707146000f, 0.431340213807410000f, 0.436812753800359000f, 59b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.442322948819202000f, 0.447870841800410000f, 0.453456475485731000f, 0.459079892424160000f, 60b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.464741134973889000f, 0.470440245304218000f, 0.476177265397440000f, 0.481952237050698000f, 61b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.487765201877811000f, 0.493616201311074000f, 0.499505276603030000f, 0.505432468828216000f, 62b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.511397818884880000f, 0.517401367496673000f, 0.523443155214325000f, 0.529523222417277000f, 63b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.535641609315311000f, 0.541798355950137000f, 0.547993502196972000f, 0.554227087766085000f, 64b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.560499152204328000f, 0.566809734896638000f, 0.573158875067523000f, 0.579546611782525000f, 65b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.585972983949661000f, 0.592438030320847000f, 0.598941789493296000f, 0.605484299910907000f, 66b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.612065599865624000f, 0.618685727498780000f, 0.625344720802427000f, 0.632042617620641000f, 67b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.638779455650817000f, 0.645555272444935000f, 0.652370105410821000f, 0.659223991813387000f, 68b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.666116968775851000f, 0.673049073280942000f, 0.680020342172095000f, 0.687030812154625000f, 69b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.694080519796882000f, 0.701169501531402000f, 0.708297793656032000f, 0.715465432335048000f, 70b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.722672453600255000f, 0.729918893352071000f, 0.737204787360605000f, 0.744530171266715000f, 71b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.751895080583051000f, 0.759299550695091000f, 0.766743616862161000f, 0.774227314218442000f, 72b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.781750677773962000f, 0.789313742415586000f, 0.796916542907978000f, 0.804559113894567000f, 73b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.812241489898490000f, 0.819963705323528000f, 0.827725794455034000f, 0.835527791460841000f, 74b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.843369730392169000f, 0.851251645184515000f, 0.859173569658532000f, 0.867135537520905000f, 75b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.875137582365205000f, 0.883179737672745000f, 0.891262036813419000f, 0.899384513046529000f, 76b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.907547199521614000f, 0.915750129279253000f, 0.923993335251873000f, 0.932276850264543000f, 77b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.940600707035753000f, 0.948964938178195000f, 0.957369576199527000f, 0.965814653503130000f, 78b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0.974300202388861000f, 0.982826255053791000f, 0.991392843592940000f, 1.000000000000000000f, 79b39067696ad08a26bbe49b71a71f0546dc42a075msarett}; 80b39067696ad08a26bbe49b71a71f0546dc42a075msarett 81b39067696ad08a26bbe49b71a71f0546dc42a075msarettstatic void build_table_linear_from_gamma(float* outTable, float exponent) { 82b39067696ad08a26bbe49b71a71f0546dc42a075msarett for (float x = 0.0f; x <= 1.0f; x += (1.0f/255.0f)) { 83b39067696ad08a26bbe49b71a71f0546dc42a075msarett *outTable++ = powf(x, exponent); 84b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 859876ac5b3016e5353c072378ac1545a0a2270757msarett} 869876ac5b3016e5353c072378ac1545a0a2270757msarett 87b39067696ad08a26bbe49b71a71f0546dc42a075msarett// Interpolating lookup in a variably sized table. 88b39067696ad08a26bbe49b71a71f0546dc42a075msarettstatic float interp_lut(float input, const float* table, int tableSize) { 89b39067696ad08a26bbe49b71a71f0546dc42a075msarett float index = input * (tableSize - 1); 90b39067696ad08a26bbe49b71a71f0546dc42a075msarett float diff = index - sk_float_floor2int(index); 91b39067696ad08a26bbe49b71a71f0546dc42a075msarett return table[(int) sk_float_floor2int(index)] * (1.0f - diff) + 92b39067696ad08a26bbe49b71a71f0546dc42a075msarett table[(int) sk_float_ceil2int(index)] * diff; 93b39067696ad08a26bbe49b71a71f0546dc42a075msarett} 94b39067696ad08a26bbe49b71a71f0546dc42a075msarett 95b39067696ad08a26bbe49b71a71f0546dc42a075msarett// outTable is always 256 entries, inTable may be larger or smaller. 96b39067696ad08a26bbe49b71a71f0546dc42a075msarettstatic void build_table_linear_from_gamma(float* outTable, const float* inTable, 97b39067696ad08a26bbe49b71a71f0546dc42a075msarett int inTableSize) { 98b39067696ad08a26bbe49b71a71f0546dc42a075msarett if (256 == inTableSize) { 99b39067696ad08a26bbe49b71a71f0546dc42a075msarett memcpy(outTable, inTable, sizeof(float) * 256); 100b39067696ad08a26bbe49b71a71f0546dc42a075msarett return; 101b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 102b39067696ad08a26bbe49b71a71f0546dc42a075msarett 103b39067696ad08a26bbe49b71a71f0546dc42a075msarett for (float x = 0.0f; x <= 1.0f; x += (1.0f/255.0f)) { 104b39067696ad08a26bbe49b71a71f0546dc42a075msarett *outTable++ = interp_lut(x, inTable, inTableSize); 105b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 106b39067696ad08a26bbe49b71a71f0546dc42a075msarett} 107b39067696ad08a26bbe49b71a71f0546dc42a075msarett 108b39067696ad08a26bbe49b71a71f0546dc42a075msarettstatic void build_table_linear_from_gamma(float* outTable, float g, float a, float b, float c, 109b39067696ad08a26bbe49b71a71f0546dc42a075msarett float d, float e, float f) { 110b39067696ad08a26bbe49b71a71f0546dc42a075msarett // Y = (aX + b)^g + c for X >= d 111b39067696ad08a26bbe49b71a71f0546dc42a075msarett // Y = eX + f otherwise 112b39067696ad08a26bbe49b71a71f0546dc42a075msarett for (float x = 0.0f; x <= 1.0f; x += (1.0f/255.0f)) { 113b39067696ad08a26bbe49b71a71f0546dc42a075msarett if (x >= d) { 114b39067696ad08a26bbe49b71a71f0546dc42a075msarett *outTable++ = powf(a * x + b, g) + c; 115b39067696ad08a26bbe49b71a71f0546dc42a075msarett } else { 116b39067696ad08a26bbe49b71a71f0546dc42a075msarett *outTable++ = e * x + f; 117b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 118b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 119b39067696ad08a26bbe49b71a71f0546dc42a075msarett} 120b39067696ad08a26bbe49b71a71f0546dc42a075msarett 1216006f678e78af7b6f67a454cd4bc213048983f9dmsarettstatic inline bool compute_gamut_xform(SkMatrix44* srcToDst, const SkMatrix44& srcToXYZ, 1226006f678e78af7b6f67a454cd4bc213048983f9dmsarett const SkMatrix44& dstToXYZ) { 1236006f678e78af7b6f67a454cd4bc213048983f9dmsarett if (!dstToXYZ.invert(srcToDst)) { 1246006f678e78af7b6f67a454cd4bc213048983f9dmsarett return false; 1256006f678e78af7b6f67a454cd4bc213048983f9dmsarett } 1266006f678e78af7b6f67a454cd4bc213048983f9dmsarett 1276006f678e78af7b6f67a454cd4bc213048983f9dmsarett srcToDst->postConcat(srcToXYZ); 1286006f678e78af7b6f67a454cd4bc213048983f9dmsarett return true; 1296006f678e78af7b6f67a454cd4bc213048983f9dmsarett} 1306006f678e78af7b6f67a454cd4bc213048983f9dmsarett 1316006f678e78af7b6f67a454cd4bc213048983f9dmsarett/////////////////////////////////////////////////////////////////////////////////////////////////// 1326006f678e78af7b6f67a454cd4bc213048983f9dmsarett 133b39067696ad08a26bbe49b71a71f0546dc42a075msarettstatic constexpr uint8_t linear_to_srgb[1024] = { 134b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0, 3, 6, 10, 13, 15, 18, 20, 22, 23, 25, 27, 28, 30, 31, 32, 34, 35, 135b39067696ad08a26bbe49b71a71f0546dc42a075msarett 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 49, 50, 51, 52, 136b39067696ad08a26bbe49b71a71f0546dc42a075msarett 53, 53, 54, 55, 56, 56, 57, 58, 58, 59, 60, 61, 61, 62, 62, 63, 64, 64, 137b39067696ad08a26bbe49b71a71f0546dc42a075msarett 65, 66, 66, 67, 67, 68, 68, 69, 70, 70, 71, 71, 72, 72, 73, 73, 74, 74, 138b39067696ad08a26bbe49b71a71f0546dc42a075msarett 75, 76, 76, 77, 77, 78, 78, 79, 79, 79, 80, 80, 81, 81, 82, 82, 83, 83, 139b39067696ad08a26bbe49b71a71f0546dc42a075msarett 84, 84, 85, 85, 85, 86, 86, 87, 87, 88, 88, 88, 89, 89, 90, 90, 91, 91, 140b39067696ad08a26bbe49b71a71f0546dc42a075msarett 91, 92, 92, 93, 93, 93, 94, 94, 95, 95, 95, 96, 96, 97, 97, 97, 98, 98, 141b39067696ad08a26bbe49b71a71f0546dc42a075msarett 98, 99, 99, 99, 100, 100, 101, 101, 101, 102, 102, 102, 103, 103, 103, 104, 104, 104, 142b39067696ad08a26bbe49b71a71f0546dc42a075msarett 105, 105, 106, 106, 106, 107, 107, 107, 108, 108, 108, 109, 109, 109, 110, 110, 110, 110, 143b39067696ad08a26bbe49b71a71f0546dc42a075msarett 111, 111, 111, 112, 112, 112, 113, 113, 113, 114, 114, 114, 115, 115, 115, 115, 116, 116, 144b39067696ad08a26bbe49b71a71f0546dc42a075msarett 116, 117, 117, 117, 118, 118, 118, 118, 119, 119, 119, 120, 120, 120, 121, 121, 121, 121, 145b39067696ad08a26bbe49b71a71f0546dc42a075msarett 122, 122, 122, 123, 123, 123, 123, 124, 124, 124, 125, 125, 125, 125, 126, 126, 126, 126, 146b39067696ad08a26bbe49b71a71f0546dc42a075msarett 127, 127, 127, 128, 128, 128, 128, 129, 129, 129, 129, 130, 130, 130, 130, 131, 131, 131, 147b39067696ad08a26bbe49b71a71f0546dc42a075msarett 131, 132, 132, 132, 133, 133, 133, 133, 134, 134, 134, 134, 135, 135, 135, 135, 136, 136, 148b39067696ad08a26bbe49b71a71f0546dc42a075msarett 136, 136, 137, 137, 137, 137, 138, 138, 138, 138, 138, 139, 139, 139, 139, 140, 140, 140, 149b39067696ad08a26bbe49b71a71f0546dc42a075msarett 140, 141, 141, 141, 141, 142, 142, 142, 142, 143, 143, 143, 143, 143, 144, 144, 144, 144, 150b39067696ad08a26bbe49b71a71f0546dc42a075msarett 145, 145, 145, 145, 146, 146, 146, 146, 146, 147, 147, 147, 147, 148, 148, 148, 148, 148, 151b39067696ad08a26bbe49b71a71f0546dc42a075msarett 149, 149, 149, 149, 150, 150, 150, 150, 150, 151, 151, 151, 151, 152, 152, 152, 152, 152, 152b39067696ad08a26bbe49b71a71f0546dc42a075msarett 153, 153, 153, 153, 153, 154, 154, 154, 154, 155, 155, 155, 155, 155, 156, 156, 156, 156, 153b39067696ad08a26bbe49b71a71f0546dc42a075msarett 156, 157, 157, 157, 157, 157, 158, 158, 158, 158, 158, 159, 159, 159, 159, 159, 160, 160, 154b39067696ad08a26bbe49b71a71f0546dc42a075msarett 160, 160, 160, 161, 161, 161, 161, 161, 162, 162, 162, 162, 162, 163, 163, 163, 163, 163, 155b39067696ad08a26bbe49b71a71f0546dc42a075msarett 164, 164, 164, 164, 164, 165, 165, 165, 165, 165, 166, 166, 166, 166, 166, 167, 167, 167, 156b39067696ad08a26bbe49b71a71f0546dc42a075msarett 167, 167, 168, 168, 168, 168, 168, 168, 169, 169, 169, 169, 169, 170, 170, 170, 170, 170, 157b39067696ad08a26bbe49b71a71f0546dc42a075msarett 171, 171, 171, 171, 171, 171, 172, 172, 172, 172, 172, 173, 173, 173, 173, 173, 173, 174, 158b39067696ad08a26bbe49b71a71f0546dc42a075msarett 174, 174, 174, 174, 175, 175, 175, 175, 175, 175, 176, 176, 176, 176, 176, 177, 177, 177, 159b39067696ad08a26bbe49b71a71f0546dc42a075msarett 177, 177, 177, 178, 178, 178, 178, 178, 178, 179, 179, 179, 179, 179, 179, 180, 180, 180, 160b39067696ad08a26bbe49b71a71f0546dc42a075msarett 180, 180, 181, 181, 181, 181, 181, 181, 182, 182, 182, 182, 182, 182, 183, 183, 183, 183, 161b39067696ad08a26bbe49b71a71f0546dc42a075msarett 183, 183, 184, 184, 184, 184, 184, 184, 185, 185, 185, 185, 185, 185, 186, 186, 186, 186, 162b39067696ad08a26bbe49b71a71f0546dc42a075msarett 186, 186, 187, 187, 187, 187, 187, 187, 188, 188, 188, 188, 188, 188, 189, 189, 189, 189, 163b39067696ad08a26bbe49b71a71f0546dc42a075msarett 189, 189, 190, 190, 190, 190, 190, 190, 191, 191, 191, 191, 191, 191, 191, 192, 192, 192, 164b39067696ad08a26bbe49b71a71f0546dc42a075msarett 192, 192, 192, 193, 193, 193, 193, 193, 193, 194, 194, 194, 194, 194, 194, 194, 195, 195, 165b39067696ad08a26bbe49b71a71f0546dc42a075msarett 195, 195, 195, 195, 196, 196, 196, 196, 196, 196, 197, 197, 197, 197, 197, 197, 197, 198, 166b39067696ad08a26bbe49b71a71f0546dc42a075msarett 198, 198, 198, 198, 198, 199, 199, 199, 199, 199, 199, 199, 200, 200, 200, 200, 200, 200, 167b39067696ad08a26bbe49b71a71f0546dc42a075msarett 200, 201, 201, 201, 201, 201, 201, 202, 202, 202, 202, 202, 202, 202, 203, 203, 203, 203, 168b39067696ad08a26bbe49b71a71f0546dc42a075msarett 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 205, 205, 205, 205, 205, 205, 206, 206, 169b39067696ad08a26bbe49b71a71f0546dc42a075msarett 206, 206, 206, 206, 206, 207, 207, 207, 207, 207, 207, 207, 208, 208, 208, 208, 208, 208, 170b39067696ad08a26bbe49b71a71f0546dc42a075msarett 208, 209, 209, 209, 209, 209, 209, 209, 210, 210, 210, 210, 210, 210, 210, 211, 211, 211, 171b39067696ad08a26bbe49b71a71f0546dc42a075msarett 211, 211, 211, 211, 212, 212, 212, 212, 212, 212, 212, 212, 213, 213, 213, 213, 213, 213, 172b39067696ad08a26bbe49b71a71f0546dc42a075msarett 213, 214, 214, 214, 214, 214, 214, 214, 215, 215, 215, 215, 215, 215, 215, 216, 216, 216, 173b39067696ad08a26bbe49b71a71f0546dc42a075msarett 216, 216, 216, 216, 216, 217, 217, 217, 217, 217, 217, 217, 218, 218, 218, 218, 218, 218, 174b39067696ad08a26bbe49b71a71f0546dc42a075msarett 218, 219, 219, 219, 219, 219, 219, 219, 219, 220, 220, 220, 220, 220, 220, 220, 221, 221, 175b39067696ad08a26bbe49b71a71f0546dc42a075msarett 221, 221, 221, 221, 221, 221, 222, 222, 222, 222, 222, 222, 222, 222, 223, 223, 223, 223, 176b39067696ad08a26bbe49b71a71f0546dc42a075msarett 223, 223, 223, 224, 224, 224, 224, 224, 224, 224, 224, 225, 225, 225, 225, 225, 225, 225, 177b39067696ad08a26bbe49b71a71f0546dc42a075msarett 225, 226, 226, 226, 226, 226, 226, 226, 227, 227, 227, 227, 227, 227, 227, 227, 228, 228, 178b39067696ad08a26bbe49b71a71f0546dc42a075msarett 228, 228, 228, 228, 228, 228, 229, 229, 229, 229, 229, 229, 229, 229, 230, 230, 230, 230, 179b39067696ad08a26bbe49b71a71f0546dc42a075msarett 230, 230, 230, 230, 231, 231, 231, 231, 231, 231, 231, 231, 232, 232, 232, 232, 232, 232, 180b39067696ad08a26bbe49b71a71f0546dc42a075msarett 232, 232, 233, 233, 233, 233, 233, 233, 233, 233, 234, 234, 234, 234, 234, 234, 234, 234, 181b39067696ad08a26bbe49b71a71f0546dc42a075msarett 235, 235, 235, 235, 235, 235, 235, 235, 236, 236, 236, 236, 236, 236, 236, 236, 236, 237, 182b39067696ad08a26bbe49b71a71f0546dc42a075msarett 237, 237, 237, 237, 237, 237, 237, 238, 238, 238, 238, 238, 238, 238, 238, 239, 239, 239, 183b39067696ad08a26bbe49b71a71f0546dc42a075msarett 239, 239, 239, 239, 239, 239, 240, 240, 240, 240, 240, 240, 240, 240, 241, 241, 241, 241, 184b39067696ad08a26bbe49b71a71f0546dc42a075msarett 241, 241, 241, 241, 241, 242, 242, 242, 242, 242, 242, 242, 242, 243, 243, 243, 243, 243, 185b39067696ad08a26bbe49b71a71f0546dc42a075msarett 243, 243, 243, 243, 244, 244, 244, 244, 244, 244, 244, 244, 245, 245, 245, 245, 245, 245, 186b39067696ad08a26bbe49b71a71f0546dc42a075msarett 245, 245, 245, 246, 246, 246, 246, 246, 246, 246, 246, 246, 247, 247, 247, 247, 247, 247, 187b39067696ad08a26bbe49b71a71f0546dc42a075msarett 247, 247, 248, 248, 248, 248, 248, 248, 248, 248, 248, 249, 249, 249, 249, 249, 249, 249, 188b39067696ad08a26bbe49b71a71f0546dc42a075msarett 249, 249, 250, 250, 250, 250, 250, 250, 250, 250, 250, 251, 251, 251, 251, 251, 251, 251, 189b39067696ad08a26bbe49b71a71f0546dc42a075msarett 251, 251, 252, 252, 252, 252, 252, 252, 252, 252, 252, 253, 253, 253, 253, 253, 253, 253, 190b39067696ad08a26bbe49b71a71f0546dc42a075msarett 253, 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 255, 255, 255, 255, 255 191b39067696ad08a26bbe49b71a71f0546dc42a075msarett}; 192b39067696ad08a26bbe49b71a71f0546dc42a075msarett 193b39067696ad08a26bbe49b71a71f0546dc42a075msarettstatic constexpr uint8_t linear_to_2dot2[1024] = { 194b39067696ad08a26bbe49b71a71f0546dc42a075msarett 0, 11, 15, 18, 21, 23, 25, 26, 28, 30, 31, 32, 34, 35, 36, 37, 39, 40, 195b39067696ad08a26bbe49b71a71f0546dc42a075msarett 41, 42, 43, 44, 45, 45, 46, 47, 48, 49, 50, 50, 51, 52, 53, 54, 54, 55, 196b39067696ad08a26bbe49b71a71f0546dc42a075msarett 56, 56, 57, 58, 58, 59, 60, 60, 61, 62, 62, 63, 63, 64, 65, 65, 66, 66, 197b39067696ad08a26bbe49b71a71f0546dc42a075msarett 67, 68, 68, 69, 69, 70, 70, 71, 71, 72, 72, 73, 73, 74, 74, 75, 75, 76, 198b39067696ad08a26bbe49b71a71f0546dc42a075msarett 76, 77, 77, 78, 78, 79, 79, 80, 80, 81, 81, 81, 82, 82, 83, 83, 84, 84, 199b39067696ad08a26bbe49b71a71f0546dc42a075msarett 84, 85, 85, 86, 86, 87, 87, 87, 88, 88, 89, 89, 89, 90, 90, 91, 91, 91, 200b39067696ad08a26bbe49b71a71f0546dc42a075msarett 92, 92, 93, 93, 93, 94, 94, 94, 95, 95, 96, 96, 96, 97, 97, 97, 98, 98, 201b39067696ad08a26bbe49b71a71f0546dc42a075msarett 98, 99, 99, 99, 100, 100, 101, 101, 101, 102, 102, 102, 103, 103, 103, 104, 104, 104, 202b39067696ad08a26bbe49b71a71f0546dc42a075msarett 105, 105, 105, 106, 106, 106, 107, 107, 107, 108, 108, 108, 108, 109, 109, 109, 110, 110, 203b39067696ad08a26bbe49b71a71f0546dc42a075msarett 110, 111, 111, 111, 112, 112, 112, 112, 113, 113, 113, 114, 114, 114, 115, 115, 115, 115, 204b39067696ad08a26bbe49b71a71f0546dc42a075msarett 116, 116, 116, 117, 117, 117, 117, 118, 118, 118, 119, 119, 119, 119, 120, 120, 120, 121, 205b39067696ad08a26bbe49b71a71f0546dc42a075msarett 121, 121, 121, 122, 122, 122, 123, 123, 123, 123, 124, 124, 124, 124, 125, 125, 125, 125, 206b39067696ad08a26bbe49b71a71f0546dc42a075msarett 126, 126, 126, 127, 127, 127, 127, 128, 128, 128, 128, 129, 129, 129, 129, 130, 130, 130, 207b39067696ad08a26bbe49b71a71f0546dc42a075msarett 130, 131, 131, 131, 131, 132, 132, 132, 132, 133, 133, 133, 133, 134, 134, 134, 134, 135, 208b39067696ad08a26bbe49b71a71f0546dc42a075msarett 135, 135, 135, 136, 136, 136, 136, 137, 137, 137, 137, 138, 138, 138, 138, 138, 139, 139, 209b39067696ad08a26bbe49b71a71f0546dc42a075msarett 139, 139, 140, 140, 140, 140, 141, 141, 141, 141, 142, 142, 142, 142, 142, 143, 143, 143, 210b39067696ad08a26bbe49b71a71f0546dc42a075msarett 143, 144, 144, 144, 144, 144, 145, 145, 145, 145, 146, 146, 146, 146, 146, 147, 147, 147, 211b39067696ad08a26bbe49b71a71f0546dc42a075msarett 147, 148, 148, 148, 148, 148, 149, 149, 149, 149, 149, 150, 150, 150, 150, 151, 151, 151, 212b39067696ad08a26bbe49b71a71f0546dc42a075msarett 151, 151, 152, 152, 152, 152, 152, 153, 153, 153, 153, 154, 154, 154, 154, 154, 155, 155, 213b39067696ad08a26bbe49b71a71f0546dc42a075msarett 155, 155, 155, 156, 156, 156, 156, 156, 157, 157, 157, 157, 157, 158, 158, 158, 158, 158, 214b39067696ad08a26bbe49b71a71f0546dc42a075msarett 159, 159, 159, 159, 159, 160, 160, 160, 160, 160, 161, 161, 161, 161, 161, 162, 162, 162, 215b39067696ad08a26bbe49b71a71f0546dc42a075msarett 162, 162, 163, 163, 163, 163, 163, 164, 164, 164, 164, 164, 165, 165, 165, 165, 165, 165, 216b39067696ad08a26bbe49b71a71f0546dc42a075msarett 166, 166, 166, 166, 166, 167, 167, 167, 167, 167, 168, 168, 168, 168, 168, 168, 169, 169, 217b39067696ad08a26bbe49b71a71f0546dc42a075msarett 169, 169, 169, 170, 170, 170, 170, 170, 171, 171, 171, 171, 171, 171, 172, 172, 172, 172, 218b39067696ad08a26bbe49b71a71f0546dc42a075msarett 172, 173, 173, 173, 173, 173, 173, 174, 174, 174, 174, 174, 174, 175, 175, 175, 175, 175, 219b39067696ad08a26bbe49b71a71f0546dc42a075msarett 176, 176, 176, 176, 176, 176, 177, 177, 177, 177, 177, 177, 178, 178, 178, 178, 178, 179, 220b39067696ad08a26bbe49b71a71f0546dc42a075msarett 179, 179, 179, 179, 179, 180, 180, 180, 180, 180, 180, 181, 181, 181, 181, 181, 181, 182, 221b39067696ad08a26bbe49b71a71f0546dc42a075msarett 182, 182, 182, 182, 182, 183, 183, 183, 183, 183, 183, 184, 184, 184, 184, 184, 185, 185, 222b39067696ad08a26bbe49b71a71f0546dc42a075msarett 185, 185, 185, 185, 186, 186, 186, 186, 186, 186, 186, 187, 187, 187, 187, 187, 187, 188, 223b39067696ad08a26bbe49b71a71f0546dc42a075msarett 188, 188, 188, 188, 188, 189, 189, 189, 189, 189, 189, 190, 190, 190, 190, 190, 190, 191, 224b39067696ad08a26bbe49b71a71f0546dc42a075msarett 191, 191, 191, 191, 191, 192, 192, 192, 192, 192, 192, 192, 193, 193, 193, 193, 193, 193, 225b39067696ad08a26bbe49b71a71f0546dc42a075msarett 194, 194, 194, 194, 194, 194, 195, 195, 195, 195, 195, 195, 195, 196, 196, 196, 196, 196, 226b39067696ad08a26bbe49b71a71f0546dc42a075msarett 196, 197, 197, 197, 197, 197, 197, 197, 198, 198, 198, 198, 198, 198, 199, 199, 199, 199, 227b39067696ad08a26bbe49b71a71f0546dc42a075msarett 199, 199, 199, 200, 200, 200, 200, 200, 200, 201, 201, 201, 201, 201, 201, 201, 202, 202, 228b39067696ad08a26bbe49b71a71f0546dc42a075msarett 202, 202, 202, 202, 202, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 229b39067696ad08a26bbe49b71a71f0546dc42a075msarett 205, 205, 205, 205, 205, 205, 205, 206, 206, 206, 206, 206, 206, 206, 207, 207, 207, 207, 230b39067696ad08a26bbe49b71a71f0546dc42a075msarett 207, 207, 207, 208, 208, 208, 208, 208, 208, 209, 209, 209, 209, 209, 209, 209, 210, 210, 231b39067696ad08a26bbe49b71a71f0546dc42a075msarett 210, 210, 210, 210, 210, 211, 211, 211, 211, 211, 211, 211, 212, 212, 212, 212, 212, 212, 232b39067696ad08a26bbe49b71a71f0546dc42a075msarett 212, 213, 213, 213, 213, 213, 213, 213, 213, 214, 214, 214, 214, 214, 214, 214, 215, 215, 233b39067696ad08a26bbe49b71a71f0546dc42a075msarett 215, 215, 215, 215, 215, 216, 216, 216, 216, 216, 216, 216, 217, 217, 217, 217, 217, 217, 234b39067696ad08a26bbe49b71a71f0546dc42a075msarett 217, 218, 218, 218, 218, 218, 218, 218, 218, 219, 219, 219, 219, 219, 219, 219, 220, 220, 235b39067696ad08a26bbe49b71a71f0546dc42a075msarett 220, 220, 220, 220, 220, 221, 221, 221, 221, 221, 221, 221, 221, 222, 222, 222, 222, 222, 236b39067696ad08a26bbe49b71a71f0546dc42a075msarett 222, 222, 223, 223, 223, 223, 223, 223, 223, 223, 224, 224, 224, 224, 224, 224, 224, 225, 237b39067696ad08a26bbe49b71a71f0546dc42a075msarett 225, 225, 225, 225, 225, 225, 225, 226, 226, 226, 226, 226, 226, 226, 226, 227, 227, 227, 238b39067696ad08a26bbe49b71a71f0546dc42a075msarett 227, 227, 227, 227, 228, 228, 228, 228, 228, 228, 228, 228, 229, 229, 229, 229, 229, 229, 239b39067696ad08a26bbe49b71a71f0546dc42a075msarett 229, 229, 230, 230, 230, 230, 230, 230, 230, 230, 231, 231, 231, 231, 231, 231, 231, 232, 240b39067696ad08a26bbe49b71a71f0546dc42a075msarett 232, 232, 232, 232, 232, 232, 232, 233, 233, 233, 233, 233, 233, 233, 233, 234, 234, 234, 241b39067696ad08a26bbe49b71a71f0546dc42a075msarett 234, 234, 234, 234, 234, 235, 235, 235, 235, 235, 235, 235, 235, 236, 236, 236, 236, 236, 242b39067696ad08a26bbe49b71a71f0546dc42a075msarett 236, 236, 236, 237, 237, 237, 237, 237, 237, 237, 237, 238, 238, 238, 238, 238, 238, 238, 243b39067696ad08a26bbe49b71a71f0546dc42a075msarett 238, 238, 239, 239, 239, 239, 239, 239, 239, 239, 240, 240, 240, 240, 240, 240, 240, 240, 244b39067696ad08a26bbe49b71a71f0546dc42a075msarett 241, 241, 241, 241, 241, 241, 241, 241, 242, 242, 242, 242, 242, 242, 242, 242, 243, 243, 245b39067696ad08a26bbe49b71a71f0546dc42a075msarett 243, 243, 243, 243, 243, 243, 243, 244, 244, 244, 244, 244, 244, 244, 244, 245, 245, 245, 246b39067696ad08a26bbe49b71a71f0546dc42a075msarett 245, 245, 245, 245, 245, 245, 246, 246, 246, 246, 246, 246, 246, 246, 247, 247, 247, 247, 247b39067696ad08a26bbe49b71a71f0546dc42a075msarett 247, 247, 247, 247, 248, 248, 248, 248, 248, 248, 248, 248, 248, 249, 249, 249, 249, 249, 248b39067696ad08a26bbe49b71a71f0546dc42a075msarett 249, 249, 249, 249, 250, 250, 250, 250, 250, 250, 250, 250, 251, 251, 251, 251, 251, 251, 249b39067696ad08a26bbe49b71a71f0546dc42a075msarett 251, 251, 251, 252, 252, 252, 252, 252, 252, 252, 252, 252, 253, 253, 253, 253, 253, 253, 250b39067696ad08a26bbe49b71a71f0546dc42a075msarett 253, 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 255, 255, 255, 255, 255, 251b39067696ad08a26bbe49b71a71f0546dc42a075msarett}; 252b39067696ad08a26bbe49b71a71f0546dc42a075msarett 253a9e878c836994bce695274b4c28890290139dcdfmsarett// Expand range from 0-1 to 0-255, then convert. 254b39067696ad08a26bbe49b71a71f0546dc42a075msarettstatic uint8_t clamp_normalized_float_to_byte(float v) { 255dea0340cadb759932e53416a657f5ea75fee8b5fmsarett // The ordering of the logic is a little strange here in order 256dea0340cadb759932e53416a657f5ea75fee8b5fmsarett // to make sure we convert NaNs to 0. 2579876ac5b3016e5353c072378ac1545a0a2270757msarett v = v * 255.0f; 258a9e878c836994bce695274b4c28890290139dcdfmsarett if (v >= 254.5f) { 2599876ac5b3016e5353c072378ac1545a0a2270757msarett return 255; 260dea0340cadb759932e53416a657f5ea75fee8b5fmsarett } else if (v >= 0.5f) { 2619876ac5b3016e5353c072378ac1545a0a2270757msarett return (uint8_t) (v + 0.5f); 262dea0340cadb759932e53416a657f5ea75fee8b5fmsarett } else { 263dea0340cadb759932e53416a657f5ea75fee8b5fmsarett return 0; 2649876ac5b3016e5353c072378ac1545a0a2270757msarett } 2659876ac5b3016e5353c072378ac1545a0a2270757msarett} 2669876ac5b3016e5353c072378ac1545a0a2270757msarett 2671b93bd1e6eba3d14593490e4e24a34546638c8damsarettstatic void build_table_linear_to_gamma(uint8_t* outTable, float exponent) { 268b39067696ad08a26bbe49b71a71f0546dc42a075msarett float toGammaExp = 1.0f / exponent; 269b39067696ad08a26bbe49b71a71f0546dc42a075msarett 2701b93bd1e6eba3d14593490e4e24a34546638c8damsarett for (int i = 0; i < SkDefaultXform::kDstGammaTableSize; i++) { 2711b93bd1e6eba3d14593490e4e24a34546638c8damsarett float x = ((float) i) * (1.0f / ((float) (SkDefaultXform::kDstGammaTableSize - 1))); 272b39067696ad08a26bbe49b71a71f0546dc42a075msarett outTable[i] = clamp_normalized_float_to_byte(powf(x, toGammaExp)); 273b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 274dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett} 275dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett 276dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett// Inverse table lookup. Ex: what index corresponds to the input value? This will 277dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett// have strange results when the table is non-increasing. But any sane gamma 278dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett// function will be increasing. 2791b93bd1e6eba3d14593490e4e24a34546638c8damsarettstatic float inverse_interp_lut(float input, const float* table, int tableSize) { 280dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett if (input <= table[0]) { 281dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett return table[0]; 282dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett } else if (input >= table[tableSize - 1]) { 283dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett return 1.0f; 284dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett } 285dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett 286b39067696ad08a26bbe49b71a71f0546dc42a075msarett for (int i = 1; i < tableSize; i++) { 287dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett if (table[i] >= input) { 288dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett // We are guaranteed that input is greater than table[i - 1]. 289dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett float diff = input - table[i - 1]; 290dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett float distance = table[i] - table[i - 1]; 291dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett float index = (i - 1) + diff / distance; 292dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett return index / (tableSize - 1); 293dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett } 294dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett } 295dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett 296dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett // Should be unreachable, since we'll return before the loop if input is 297dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett // larger than the last entry. 298dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett SkASSERT(false); 299dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett return 0.0f; 300dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett} 301dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett 3021b93bd1e6eba3d14593490e4e24a34546638c8damsarettstatic void build_table_linear_to_gamma(uint8_t* outTable, const float* inTable, 303b39067696ad08a26bbe49b71a71f0546dc42a075msarett int inTableSize) { 3041b93bd1e6eba3d14593490e4e24a34546638c8damsarett for (int i = 0; i < SkDefaultXform::kDstGammaTableSize; i++) { 3051b93bd1e6eba3d14593490e4e24a34546638c8damsarett float x = ((float) i) * (1.0f / ((float) (SkDefaultXform::kDstGammaTableSize - 1))); 306b39067696ad08a26bbe49b71a71f0546dc42a075msarett float y = inverse_interp_lut(x, inTable, inTableSize); 307b39067696ad08a26bbe49b71a71f0546dc42a075msarett outTable[i] = clamp_normalized_float_to_byte(y); 308b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 309b39067696ad08a26bbe49b71a71f0546dc42a075msarett} 310dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett 311b39067696ad08a26bbe49b71a71f0546dc42a075msarettstatic float inverse_parametric(float x, float g, float a, float b, float c, float d, float e, 312b39067696ad08a26bbe49b71a71f0546dc42a075msarett float f) { 313b39067696ad08a26bbe49b71a71f0546dc42a075msarett // We need to take the inverse of the following piecewise function. 314b39067696ad08a26bbe49b71a71f0546dc42a075msarett // Y = (aX + b)^g + c for X >= d 315b39067696ad08a26bbe49b71a71f0546dc42a075msarett // Y = eX + f otherwise 316b39067696ad08a26bbe49b71a71f0546dc42a075msarett 317b39067696ad08a26bbe49b71a71f0546dc42a075msarett // Assume that the gamma function is continuous, or this won't make much sense anyway. 318b39067696ad08a26bbe49b71a71f0546dc42a075msarett // Plug in |d| to the first equation to calculate the new piecewise interval. 319b39067696ad08a26bbe49b71a71f0546dc42a075msarett // Then simply use the inverse of the original functions. 320b39067696ad08a26bbe49b71a71f0546dc42a075msarett float interval = e * d + f; 321b39067696ad08a26bbe49b71a71f0546dc42a075msarett if (x < interval) { 322b39067696ad08a26bbe49b71a71f0546dc42a075msarett // X = (Y - F) / E 323b39067696ad08a26bbe49b71a71f0546dc42a075msarett if (0.0f == e) { 324b39067696ad08a26bbe49b71a71f0546dc42a075msarett // The gamma curve for this segment is constant, so the inverse is undefined. 325b39067696ad08a26bbe49b71a71f0546dc42a075msarett // Since this is the lower segment, guess zero. 326b39067696ad08a26bbe49b71a71f0546dc42a075msarett return 0.0f; 327b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 328b39067696ad08a26bbe49b71a71f0546dc42a075msarett 329b39067696ad08a26bbe49b71a71f0546dc42a075msarett return (x - f) / e; 330b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 331b39067696ad08a26bbe49b71a71f0546dc42a075msarett 332b39067696ad08a26bbe49b71a71f0546dc42a075msarett // X = ((Y - C)^(1 / G) - B) / A 333b39067696ad08a26bbe49b71a71f0546dc42a075msarett if (0.0f == a || 0.0f == g) { 334b39067696ad08a26bbe49b71a71f0546dc42a075msarett // The gamma curve for this segment is constant, so the inverse is undefined. 335b39067696ad08a26bbe49b71a71f0546dc42a075msarett // Since this is the upper segment, guess one. 336b39067696ad08a26bbe49b71a71f0546dc42a075msarett return 1.0f; 337b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 338b39067696ad08a26bbe49b71a71f0546dc42a075msarett 339b39067696ad08a26bbe49b71a71f0546dc42a075msarett return (powf(x - c, 1.0f / g) - b) / a; 340b39067696ad08a26bbe49b71a71f0546dc42a075msarett} 341b39067696ad08a26bbe49b71a71f0546dc42a075msarett 3421b93bd1e6eba3d14593490e4e24a34546638c8damsarettstatic void build_table_linear_to_gamma(uint8_t* outTable, float g, float a, 343b39067696ad08a26bbe49b71a71f0546dc42a075msarett float b, float c, float d, float e, float f) { 3441b93bd1e6eba3d14593490e4e24a34546638c8damsarett for (int i = 0; i < SkDefaultXform::kDstGammaTableSize; i++) { 3451b93bd1e6eba3d14593490e4e24a34546638c8damsarett float x = ((float) i) * (1.0f / ((float) (SkDefaultXform::kDstGammaTableSize - 1))); 346b39067696ad08a26bbe49b71a71f0546dc42a075msarett float y = inverse_parametric(x, g, a, b, c, d, e, f); 347b39067696ad08a26bbe49b71a71f0546dc42a075msarett outTable[i] = clamp_normalized_float_to_byte(y); 348b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 349b39067696ad08a26bbe49b71a71f0546dc42a075msarett} 350b39067696ad08a26bbe49b71a71f0546dc42a075msarett 3516006f678e78af7b6f67a454cd4bc213048983f9dmsarett/////////////////////////////////////////////////////////////////////////////////////////////////// 3526006f678e78af7b6f67a454cd4bc213048983f9dmsarett 3531b93bd1e6eba3d14593490e4e24a34546638c8damsaretttemplate <typename T> 3541b93bd1e6eba3d14593490e4e24a34546638c8damsarettstruct GammaFns { 3551b93bd1e6eba3d14593490e4e24a34546638c8damsarett const T* fSRGBTable; 3561b93bd1e6eba3d14593490e4e24a34546638c8damsarett const T* f2Dot2Table; 3571b93bd1e6eba3d14593490e4e24a34546638c8damsarett 3581b93bd1e6eba3d14593490e4e24a34546638c8damsarett void (*fBuildFromValue)(T*, float); 3591b93bd1e6eba3d14593490e4e24a34546638c8damsarett void (*fBuildFromTable)(T*, const float*, int); 3601b93bd1e6eba3d14593490e4e24a34546638c8damsarett void (*fBuildFromParam)(T*, float, float, float, float, float, float, float); 3611b93bd1e6eba3d14593490e4e24a34546638c8damsarett}; 3621b93bd1e6eba3d14593490e4e24a34546638c8damsarett 3631b93bd1e6eba3d14593490e4e24a34546638c8damsarettstatic const GammaFns<float> kToLinear { 3641b93bd1e6eba3d14593490e4e24a34546638c8damsarett sk_linear_from_srgb, 3651b93bd1e6eba3d14593490e4e24a34546638c8damsarett sk_linear_from_2dot2, 3661b93bd1e6eba3d14593490e4e24a34546638c8damsarett &build_table_linear_from_gamma, 3671b93bd1e6eba3d14593490e4e24a34546638c8damsarett &build_table_linear_from_gamma, 3681b93bd1e6eba3d14593490e4e24a34546638c8damsarett &build_table_linear_from_gamma, 3691b93bd1e6eba3d14593490e4e24a34546638c8damsarett}; 3701b93bd1e6eba3d14593490e4e24a34546638c8damsarett 3711b93bd1e6eba3d14593490e4e24a34546638c8damsarettstatic const GammaFns<uint8_t> kFromLinear { 3721b93bd1e6eba3d14593490e4e24a34546638c8damsarett linear_to_srgb, 3731b93bd1e6eba3d14593490e4e24a34546638c8damsarett linear_to_2dot2, 3741b93bd1e6eba3d14593490e4e24a34546638c8damsarett &build_table_linear_to_gamma, 3751b93bd1e6eba3d14593490e4e24a34546638c8damsarett &build_table_linear_to_gamma, 3761b93bd1e6eba3d14593490e4e24a34546638c8damsarett &build_table_linear_to_gamma, 3771b93bd1e6eba3d14593490e4e24a34546638c8damsarett}; 3781b93bd1e6eba3d14593490e4e24a34546638c8damsarett 3791b93bd1e6eba3d14593490e4e24a34546638c8damsarett// Build tables to transform src gamma to linear. 3801b93bd1e6eba3d14593490e4e24a34546638c8damsaretttemplate <typename T> 3811b93bd1e6eba3d14593490e4e24a34546638c8damsarettstatic void build_gamma_tables(const T* outGammaTables[3], T* gammaTableStorage, int gammaTableSize, 3821b93bd1e6eba3d14593490e4e24a34546638c8damsarett const sk_sp<SkColorSpace>& space, const GammaFns<T>& fns) { 3831b93bd1e6eba3d14593490e4e24a34546638c8damsarett switch (space->gammaNamed()) { 3841b93bd1e6eba3d14593490e4e24a34546638c8damsarett case SkColorSpace::kSRGB_GammaNamed: 3851b93bd1e6eba3d14593490e4e24a34546638c8damsarett outGammaTables[0] = outGammaTables[1] = outGammaTables[2] = fns.fSRGBTable; 3861b93bd1e6eba3d14593490e4e24a34546638c8damsarett break; 3871b93bd1e6eba3d14593490e4e24a34546638c8damsarett case SkColorSpace::k2Dot2Curve_GammaNamed: 3881b93bd1e6eba3d14593490e4e24a34546638c8damsarett outGammaTables[0] = outGammaTables[1] = outGammaTables[2] = fns.f2Dot2Table; 3891b93bd1e6eba3d14593490e4e24a34546638c8damsarett break; 3901b93bd1e6eba3d14593490e4e24a34546638c8damsarett case SkColorSpace::kLinear_GammaNamed: 3911b93bd1e6eba3d14593490e4e24a34546638c8damsarett (*fns.fBuildFromValue)(gammaTableStorage, 1.0f); 3921b93bd1e6eba3d14593490e4e24a34546638c8damsarett outGammaTables[0] = outGammaTables[1] = outGammaTables[2] = gammaTableStorage; 3931b93bd1e6eba3d14593490e4e24a34546638c8damsarett break; 3941b93bd1e6eba3d14593490e4e24a34546638c8damsarett default: { 3951b93bd1e6eba3d14593490e4e24a34546638c8damsarett const SkGammas* gammas = as_CSB(space)->gammas(); 3961b93bd1e6eba3d14593490e4e24a34546638c8damsarett SkASSERT(gammas); 3971b93bd1e6eba3d14593490e4e24a34546638c8damsarett 3981b93bd1e6eba3d14593490e4e24a34546638c8damsarett for (int i = 0; i < 3; i++) { 3991b93bd1e6eba3d14593490e4e24a34546638c8damsarett if (i > 0) { 4001b93bd1e6eba3d14593490e4e24a34546638c8damsarett // Check if this curve matches the first curve. In this case, we can 4011b93bd1e6eba3d14593490e4e24a34546638c8damsarett // share the same table pointer. This should almost always be true. 4021b93bd1e6eba3d14593490e4e24a34546638c8damsarett // I've never seen a profile where all three gamma curves didn't match. 4031b93bd1e6eba3d14593490e4e24a34546638c8damsarett // But it is possible that they won't. 4041b93bd1e6eba3d14593490e4e24a34546638c8damsarett if (gammas->data(0) == gammas->data(i)) { 4051b93bd1e6eba3d14593490e4e24a34546638c8damsarett outGammaTables[i] = outGammaTables[0]; 4061b93bd1e6eba3d14593490e4e24a34546638c8damsarett continue; 4071b93bd1e6eba3d14593490e4e24a34546638c8damsarett } 4081b93bd1e6eba3d14593490e4e24a34546638c8damsarett } 4091b93bd1e6eba3d14593490e4e24a34546638c8damsarett 4101b93bd1e6eba3d14593490e4e24a34546638c8damsarett if (gammas->isNamed(i)) { 4111b93bd1e6eba3d14593490e4e24a34546638c8damsarett switch (gammas->data(i).fNamed) { 4121b93bd1e6eba3d14593490e4e24a34546638c8damsarett case SkColorSpace::kSRGB_GammaNamed: 4131b93bd1e6eba3d14593490e4e24a34546638c8damsarett outGammaTables[i] = fns.fSRGBTable; 4141b93bd1e6eba3d14593490e4e24a34546638c8damsarett break; 4151b93bd1e6eba3d14593490e4e24a34546638c8damsarett case SkColorSpace::k2Dot2Curve_GammaNamed: 4161b93bd1e6eba3d14593490e4e24a34546638c8damsarett outGammaTables[i] = fns.f2Dot2Table; 4171b93bd1e6eba3d14593490e4e24a34546638c8damsarett break; 4181b93bd1e6eba3d14593490e4e24a34546638c8damsarett case SkColorSpace::kLinear_GammaNamed: 4191b93bd1e6eba3d14593490e4e24a34546638c8damsarett (*fns.fBuildFromValue)(&gammaTableStorage[i * gammaTableSize], 1.0f); 4201b93bd1e6eba3d14593490e4e24a34546638c8damsarett outGammaTables[i] = &gammaTableStorage[i * gammaTableSize]; 4211b93bd1e6eba3d14593490e4e24a34546638c8damsarett break; 4221b93bd1e6eba3d14593490e4e24a34546638c8damsarett default: 4231b93bd1e6eba3d14593490e4e24a34546638c8damsarett SkASSERT(false); 4241b93bd1e6eba3d14593490e4e24a34546638c8damsarett break; 4251b93bd1e6eba3d14593490e4e24a34546638c8damsarett } 4261b93bd1e6eba3d14593490e4e24a34546638c8damsarett } else if (gammas->isValue(i)) { 4271b93bd1e6eba3d14593490e4e24a34546638c8damsarett (*fns.fBuildFromValue)(&gammaTableStorage[i * gammaTableSize], 4281b93bd1e6eba3d14593490e4e24a34546638c8damsarett gammas->data(i).fValue); 4291b93bd1e6eba3d14593490e4e24a34546638c8damsarett outGammaTables[i] = &gammaTableStorage[i * gammaTableSize]; 4301b93bd1e6eba3d14593490e4e24a34546638c8damsarett } else if (gammas->isTable(i)) { 4311b93bd1e6eba3d14593490e4e24a34546638c8damsarett (*fns.fBuildFromTable)(&gammaTableStorage[i * gammaTableSize], gammas->table(i), 4321b93bd1e6eba3d14593490e4e24a34546638c8damsarett gammas->data(i).fTable.fSize); 4331b93bd1e6eba3d14593490e4e24a34546638c8damsarett outGammaTables[i] = &gammaTableStorage[i * gammaTableSize]; 4341b93bd1e6eba3d14593490e4e24a34546638c8damsarett } else { 4351b93bd1e6eba3d14593490e4e24a34546638c8damsarett SkASSERT(gammas->isParametric(i)); 4361b93bd1e6eba3d14593490e4e24a34546638c8damsarett const SkGammas::Params& params = gammas->params(i); 4371b93bd1e6eba3d14593490e4e24a34546638c8damsarett (*fns.fBuildFromParam)(&gammaTableStorage[i * gammaTableSize], params.fG, 4381b93bd1e6eba3d14593490e4e24a34546638c8damsarett params.fA, params.fB, params.fC, params.fD, params.fE, 4391b93bd1e6eba3d14593490e4e24a34546638c8damsarett params.fF); 4401b93bd1e6eba3d14593490e4e24a34546638c8damsarett outGammaTables[i] = &gammaTableStorage[i * gammaTableSize]; 4411b93bd1e6eba3d14593490e4e24a34546638c8damsarett } 4421b93bd1e6eba3d14593490e4e24a34546638c8damsarett } 4431b93bd1e6eba3d14593490e4e24a34546638c8damsarett } 4441b93bd1e6eba3d14593490e4e24a34546638c8damsarett } 4451b93bd1e6eba3d14593490e4e24a34546638c8damsarett} 4461b93bd1e6eba3d14593490e4e24a34546638c8damsarett 4471b93bd1e6eba3d14593490e4e24a34546638c8damsarett/////////////////////////////////////////////////////////////////////////////////////////////////// 4481b93bd1e6eba3d14593490e4e24a34546638c8damsarett 4496006f678e78af7b6f67a454cd4bc213048983f9dmsarettstd::unique_ptr<SkColorSpaceXform> SkColorSpaceXform::New(const sk_sp<SkColorSpace>& srcSpace, 4506006f678e78af7b6f67a454cd4bc213048983f9dmsarett const sk_sp<SkColorSpace>& dstSpace) { 4516006f678e78af7b6f67a454cd4bc213048983f9dmsarett if (!srcSpace || !dstSpace) { 4526006f678e78af7b6f67a454cd4bc213048983f9dmsarett // Invalid input 4536006f678e78af7b6f67a454cd4bc213048983f9dmsarett return nullptr; 4546006f678e78af7b6f67a454cd4bc213048983f9dmsarett } 4556006f678e78af7b6f67a454cd4bc213048983f9dmsarett 4566006f678e78af7b6f67a454cd4bc213048983f9dmsarett if (as_CSB(dstSpace)->colorLUT()) { 4576006f678e78af7b6f67a454cd4bc213048983f9dmsarett // It would be really weird for a dst profile to have a color LUT. I don't think 4586006f678e78af7b6f67a454cd4bc213048983f9dmsarett // we need to support this. 4596006f678e78af7b6f67a454cd4bc213048983f9dmsarett return nullptr; 4606006f678e78af7b6f67a454cd4bc213048983f9dmsarett } 4616006f678e78af7b6f67a454cd4bc213048983f9dmsarett 4626006f678e78af7b6f67a454cd4bc213048983f9dmsarett SkMatrix44 srcToDst(SkMatrix44::kUninitialized_Constructor); 4636006f678e78af7b6f67a454cd4bc213048983f9dmsarett if (!compute_gamut_xform(&srcToDst, srcSpace->xyz(), dstSpace->xyz())) { 4646006f678e78af7b6f67a454cd4bc213048983f9dmsarett return nullptr; 4656006f678e78af7b6f67a454cd4bc213048983f9dmsarett } 4666006f678e78af7b6f67a454cd4bc213048983f9dmsarett 4676006f678e78af7b6f67a454cd4bc213048983f9dmsarett if (0.0f == srcToDst.getFloat(3, 0) && 4686006f678e78af7b6f67a454cd4bc213048983f9dmsarett 0.0f == srcToDst.getFloat(3, 1) && 4696006f678e78af7b6f67a454cd4bc213048983f9dmsarett 0.0f == srcToDst.getFloat(3, 2) && 4706006f678e78af7b6f67a454cd4bc213048983f9dmsarett !as_CSB(srcSpace)->colorLUT()) 4716006f678e78af7b6f67a454cd4bc213048983f9dmsarett { 4726006f678e78af7b6f67a454cd4bc213048983f9dmsarett switch (dstSpace->gammaNamed()) { 4736006f678e78af7b6f67a454cd4bc213048983f9dmsarett case SkColorSpace::kSRGB_GammaNamed: 4746006f678e78af7b6f67a454cd4bc213048983f9dmsarett return std::unique_ptr<SkColorSpaceXform>( 4756006f678e78af7b6f67a454cd4bc213048983f9dmsarett new SkFastXform<SkColorSpace::kSRGB_GammaNamed>(srcSpace, srcToDst, 4766006f678e78af7b6f67a454cd4bc213048983f9dmsarett dstSpace)); 4776006f678e78af7b6f67a454cd4bc213048983f9dmsarett case SkColorSpace::k2Dot2Curve_GammaNamed: 4786006f678e78af7b6f67a454cd4bc213048983f9dmsarett return std::unique_ptr<SkColorSpaceXform>( 4796006f678e78af7b6f67a454cd4bc213048983f9dmsarett new SkFastXform<SkColorSpace::k2Dot2Curve_GammaNamed>(srcSpace, srcToDst, 4806006f678e78af7b6f67a454cd4bc213048983f9dmsarett dstSpace)); 4816006f678e78af7b6f67a454cd4bc213048983f9dmsarett default: 4826006f678e78af7b6f67a454cd4bc213048983f9dmsarett return std::unique_ptr<SkColorSpaceXform>( 4836006f678e78af7b6f67a454cd4bc213048983f9dmsarett new SkFastXform<SkColorSpace::kNonStandard_GammaNamed>(srcSpace, srcToDst, 4846006f678e78af7b6f67a454cd4bc213048983f9dmsarett dstSpace)); 4856006f678e78af7b6f67a454cd4bc213048983f9dmsarett } 4866006f678e78af7b6f67a454cd4bc213048983f9dmsarett } 4876006f678e78af7b6f67a454cd4bc213048983f9dmsarett 4886006f678e78af7b6f67a454cd4bc213048983f9dmsarett return std::unique_ptr<SkColorSpaceXform>(new SkDefaultXform(srcSpace, srcToDst, dstSpace)); 4896006f678e78af7b6f67a454cd4bc213048983f9dmsarett} 4906006f678e78af7b6f67a454cd4bc213048983f9dmsarett 4916006f678e78af7b6f67a454cd4bc213048983f9dmsarett/////////////////////////////////////////////////////////////////////////////////////////////////// 4926006f678e78af7b6f67a454cd4bc213048983f9dmsarett 4939ce3a543c92a73e6daca420defc042886b3f2019msarett// TODO (msarett): 4949ce3a543c92a73e6daca420defc042886b3f2019msarett// Once SkFastXform supports translation, delete this function and use asRowMajorf(). 4956006f678e78af7b6f67a454cd4bc213048983f9dmsarettstatic void build_src_to_dst(float srcToDstArray[12], const SkMatrix44& srcToDstMatrix) { 4966006f678e78af7b6f67a454cd4bc213048983f9dmsarett // Build the following row major matrix: 4976006f678e78af7b6f67a454cd4bc213048983f9dmsarett // rX gX bX 0 4986006f678e78af7b6f67a454cd4bc213048983f9dmsarett // rY gY bY 0 4996006f678e78af7b6f67a454cd4bc213048983f9dmsarett // rZ gZ bZ 0 5006006f678e78af7b6f67a454cd4bc213048983f9dmsarett srcToDstArray[0] = srcToDstMatrix.getFloat(0, 0); 5016006f678e78af7b6f67a454cd4bc213048983f9dmsarett srcToDstArray[1] = srcToDstMatrix.getFloat(0, 1); 5026006f678e78af7b6f67a454cd4bc213048983f9dmsarett srcToDstArray[2] = srcToDstMatrix.getFloat(0, 2); 5036006f678e78af7b6f67a454cd4bc213048983f9dmsarett srcToDstArray[3] = 0.0f; 5046006f678e78af7b6f67a454cd4bc213048983f9dmsarett srcToDstArray[4] = srcToDstMatrix.getFloat(1, 0); 5056006f678e78af7b6f67a454cd4bc213048983f9dmsarett srcToDstArray[5] = srcToDstMatrix.getFloat(1, 1); 5066006f678e78af7b6f67a454cd4bc213048983f9dmsarett srcToDstArray[6] = srcToDstMatrix.getFloat(1, 2); 5076006f678e78af7b6f67a454cd4bc213048983f9dmsarett srcToDstArray[7] = 0.0f; 5086006f678e78af7b6f67a454cd4bc213048983f9dmsarett srcToDstArray[8] = srcToDstMatrix.getFloat(2, 0); 5096006f678e78af7b6f67a454cd4bc213048983f9dmsarett srcToDstArray[9] = srcToDstMatrix.getFloat(2, 1); 5106006f678e78af7b6f67a454cd4bc213048983f9dmsarett srcToDstArray[10] = srcToDstMatrix.getFloat(2, 2); 5116006f678e78af7b6f67a454cd4bc213048983f9dmsarett srcToDstArray[11] = 0.0f; 5126006f678e78af7b6f67a454cd4bc213048983f9dmsarett} 5136006f678e78af7b6f67a454cd4bc213048983f9dmsarett 5146006f678e78af7b6f67a454cd4bc213048983f9dmsaretttemplate <SkColorSpace::GammaNamed Dst> 5156006f678e78af7b6f67a454cd4bc213048983f9dmsarettSkFastXform<Dst>::SkFastXform(const sk_sp<SkColorSpace>& srcSpace, const SkMatrix44& srcToDst, 5166006f678e78af7b6f67a454cd4bc213048983f9dmsarett const sk_sp<SkColorSpace>& dstSpace) 5176006f678e78af7b6f67a454cd4bc213048983f9dmsarett{ 5186006f678e78af7b6f67a454cd4bc213048983f9dmsarett build_src_to_dst(fSrcToDst, srcToDst); 5191b93bd1e6eba3d14593490e4e24a34546638c8damsarett build_gamma_tables(fSrcGammaTables, fSrcGammaTableStorage, 256, srcSpace, kToLinear); 5201b93bd1e6eba3d14593490e4e24a34546638c8damsarett build_gamma_tables(fDstGammaTables, fDstGammaTableStorage, SkDefaultXform::kDstGammaTableSize, 5211b93bd1e6eba3d14593490e4e24a34546638c8damsarett dstSpace, kFromLinear); 5226006f678e78af7b6f67a454cd4bc213048983f9dmsarett} 5236006f678e78af7b6f67a454cd4bc213048983f9dmsarett 5246006f678e78af7b6f67a454cd4bc213048983f9dmsaretttemplate <> 5256006f678e78af7b6f67a454cd4bc213048983f9dmsarettvoid SkFastXform<SkColorSpace::kSRGB_GammaNamed> 5269ce3a543c92a73e6daca420defc042886b3f2019msarett::applyTo8888(SkPMColor* dst, const RGBA32* src, int len) const 5276006f678e78af7b6f67a454cd4bc213048983f9dmsarett{ 5286006f678e78af7b6f67a454cd4bc213048983f9dmsarett SkOpts::color_xform_RGB1_to_srgb(dst, src, len, fSrcGammaTables, fSrcToDst); 5296006f678e78af7b6f67a454cd4bc213048983f9dmsarett} 5306006f678e78af7b6f67a454cd4bc213048983f9dmsarett 5316006f678e78af7b6f67a454cd4bc213048983f9dmsaretttemplate <> 5326006f678e78af7b6f67a454cd4bc213048983f9dmsarettvoid SkFastXform<SkColorSpace::k2Dot2Curve_GammaNamed> 5339ce3a543c92a73e6daca420defc042886b3f2019msarett::applyTo8888(SkPMColor* dst, const RGBA32* src, int len) const 5346006f678e78af7b6f67a454cd4bc213048983f9dmsarett{ 5356006f678e78af7b6f67a454cd4bc213048983f9dmsarett SkOpts::color_xform_RGB1_to_2dot2(dst, src, len, fSrcGammaTables, fSrcToDst); 5366006f678e78af7b6f67a454cd4bc213048983f9dmsarett} 5376006f678e78af7b6f67a454cd4bc213048983f9dmsarett 5386006f678e78af7b6f67a454cd4bc213048983f9dmsaretttemplate <> 5396006f678e78af7b6f67a454cd4bc213048983f9dmsarettvoid SkFastXform<SkColorSpace::kNonStandard_GammaNamed> 5409ce3a543c92a73e6daca420defc042886b3f2019msarett::applyTo8888(SkPMColor* dst, const RGBA32* src, int len) const 5416006f678e78af7b6f67a454cd4bc213048983f9dmsarett{ 5426006f678e78af7b6f67a454cd4bc213048983f9dmsarett SkOpts::color_xform_RGB1_to_table(dst, src, len, fSrcGammaTables, fSrcToDst, fDstGammaTables); 5436006f678e78af7b6f67a454cd4bc213048983f9dmsarett} 5446006f678e78af7b6f67a454cd4bc213048983f9dmsarett 5459ce3a543c92a73e6daca420defc042886b3f2019msaretttemplate <SkColorSpace::GammaNamed T> 5469ce3a543c92a73e6daca420defc042886b3f2019msarettvoid SkFastXform<T> 5479ce3a543c92a73e6daca420defc042886b3f2019msarett::applyToF16(RGBAF16* dst, const RGBA32* src, int len) const 5489ce3a543c92a73e6daca420defc042886b3f2019msarett{ 5499ce3a543c92a73e6daca420defc042886b3f2019msarett SkOpts::color_xform_RGB1_to_linear(dst, src, len, fSrcGammaTables, fSrcToDst); 5509ce3a543c92a73e6daca420defc042886b3f2019msarett} 5519ce3a543c92a73e6daca420defc042886b3f2019msarett 5526006f678e78af7b6f67a454cd4bc213048983f9dmsarett/////////////////////////////////////////////////////////////////////////////////////////////////// 5536006f678e78af7b6f67a454cd4bc213048983f9dmsarett 554b39067696ad08a26bbe49b71a71f0546dc42a075msarettSkDefaultXform::SkDefaultXform(const sk_sp<SkColorSpace>& srcSpace, const SkMatrix44& srcToDst, 555b39067696ad08a26bbe49b71a71f0546dc42a075msarett const sk_sp<SkColorSpace>& dstSpace) 5560f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett : fColorLUT(sk_ref_sp((SkColorLookUpTable*) as_CSB(srcSpace)->colorLUT())) 5570f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett , fSrcToDst(srcToDst) 558b39067696ad08a26bbe49b71a71f0546dc42a075msarett{ 5591b93bd1e6eba3d14593490e4e24a34546638c8damsarett build_gamma_tables(fSrcGammaTables, fSrcGammaTableStorage, 256, srcSpace, kToLinear); 5601b93bd1e6eba3d14593490e4e24a34546638c8damsarett build_gamma_tables(fDstGammaTables, fDstGammaTableStorage, SkDefaultXform::kDstGammaTableSize, 5611b93bd1e6eba3d14593490e4e24a34546638c8damsarett dstSpace, kFromLinear); 562b39067696ad08a26bbe49b71a71f0546dc42a075msarett} 563b39067696ad08a26bbe49b71a71f0546dc42a075msarett 5640f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarettstatic float byte_to_float(uint8_t byte) { 5650f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett return ((float) byte) * (1.0f / 255.0f); 5660f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett} 5670f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 568b39067696ad08a26bbe49b71a71f0546dc42a075msarett// Clamp to the 0-1 range. 569b39067696ad08a26bbe49b71a71f0546dc42a075msarettstatic float clamp_normalized_float(float v) { 570b39067696ad08a26bbe49b71a71f0546dc42a075msarett if (v > 1.0f) { 571b39067696ad08a26bbe49b71a71f0546dc42a075msarett return 1.0f; 572b39067696ad08a26bbe49b71a71f0546dc42a075msarett } else if ((v < 0.0f) || (v != v)) { 573b39067696ad08a26bbe49b71a71f0546dc42a075msarett return 0.0f; 574b39067696ad08a26bbe49b71a71f0546dc42a075msarett } else { 575b39067696ad08a26bbe49b71a71f0546dc42a075msarett return v; 576b39067696ad08a26bbe49b71a71f0546dc42a075msarett } 577b39067696ad08a26bbe49b71a71f0546dc42a075msarett} 578b39067696ad08a26bbe49b71a71f0546dc42a075msarett 5790f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarettstatic void interp_3d_clut(float dst[3], float src[3], const SkColorLookUpTable* colorLUT) { 5800f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // Call the src components x, y, and z. 5810f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett uint8_t maxX = colorLUT->fGridPoints[0] - 1; 5820f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett uint8_t maxY = colorLUT->fGridPoints[1] - 1; 5830f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett uint8_t maxZ = colorLUT->fGridPoints[2] - 1; 5840f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 5850f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // An approximate index into each of the three dimensions of the table. 5860f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett float x = src[0] * maxX; 5870f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett float y = src[1] * maxY; 5880f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett float z = src[2] * maxZ; 5890f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 5900f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // This gives us the low index for our interpolation. 5910f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett int ix = sk_float_floor2int(x); 5920f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett int iy = sk_float_floor2int(y); 5930f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett int iz = sk_float_floor2int(z); 5940f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 5950f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // Make sure the low index is not also the max index. 5960f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett ix = (maxX == ix) ? ix - 1 : ix; 5970f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett iy = (maxY == iy) ? iy - 1 : iy; 5980f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett iz = (maxZ == iz) ? iz - 1 : iz; 5990f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 6000f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // Weighting factors for the interpolation. 6010f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett float diffX = x - ix; 6020f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett float diffY = y - iy; 6030f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett float diffZ = z - iz; 6040f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 6050f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // Constants to help us navigate the 3D table. 6060f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // Ex: Assume x = a, y = b, z = c. 6070f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // table[a * n001 + b * n010 + c * n100] logically equals table[a][b][c]. 6080f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett const int n000 = 0; 6090f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett const int n001 = 3 * colorLUT->fGridPoints[1] * colorLUT->fGridPoints[2]; 6100f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett const int n010 = 3 * colorLUT->fGridPoints[2]; 6110f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett const int n011 = n001 + n010; 6120f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett const int n100 = 3; 6130f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett const int n101 = n100 + n001; 6140f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett const int n110 = n100 + n010; 6150f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett const int n111 = n110 + n001; 6160f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 6170f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // Base ptr into the table. 6180f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett float* ptr = &colorLUT->fTable[ix*n001 + iy*n010 + iz*n100]; 6190f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 6200f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // The code below performs a tetrahedral interpolation for each of the three 6210f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // dst components. Once the tetrahedron containing the interpolation point is 6220f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // identified, the interpolation is a weighted sum of grid values at the 6230f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // vertices of the tetrahedron. The claim is that tetrahedral interpolation 6240f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // provides a more accurate color conversion. 6250f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // blogs.mathworks.com/steve/2006/11/24/tetrahedral-interpolation-for-colorspace-conversion/ 6260f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // 6270f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // I have one test image, and visually I can't tell the difference between 6280f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // tetrahedral and trilinear interpolation. In terms of computation, the 6290f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // tetrahedral code requires more branches but less computation. The 6300f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // SampleICC library provides an option for the client to choose either 6310f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // tetrahedral or trilinear. 6320f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett for (int i = 0; i < 3; i++) { 6330f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett if (diffZ < diffY) { 6340f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett if (diffZ < diffX) { 6350f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett dst[i] = (ptr[n000] + diffZ * (ptr[n110] - ptr[n010]) + 6360f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett diffY * (ptr[n010] - ptr[n000]) + 6370f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett diffX * (ptr[n111] - ptr[n110])); 6380f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett } else if (diffY < diffX) { 6390f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett dst[i] = (ptr[n000] + diffZ * (ptr[n111] - ptr[n011]) + 6400f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett diffY * (ptr[n011] - ptr[n001]) + 6410f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett diffX * (ptr[n001] - ptr[n000])); 6420f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett } else { 6430f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett dst[i] = (ptr[n000] + diffZ * (ptr[n111] - ptr[n011]) + 6440f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett diffY * (ptr[n010] - ptr[n000]) + 6450f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett diffX * (ptr[n011] - ptr[n010])); 6460f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett } 6470f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett } else { 6480f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett if (diffZ < diffX) { 6490f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett dst[i] = (ptr[n000] + diffZ * (ptr[n101] - ptr[n001]) + 6500f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett diffY * (ptr[n111] - ptr[n101]) + 6510f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett diffX * (ptr[n001] - ptr[n000])); 6520f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett } else if (diffY < diffX) { 6530f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett dst[i] = (ptr[n000] + diffZ * (ptr[n100] - ptr[n000]) + 6540f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett diffY * (ptr[n111] - ptr[n101]) + 6550f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett diffX * (ptr[n101] - ptr[n100])); 6560f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett } else { 6570f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett dst[i] = (ptr[n000] + diffZ * (ptr[n100] - ptr[n000]) + 6580f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett diffY * (ptr[n110] - ptr[n100]) + 6590f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett diffX * (ptr[n111] - ptr[n110])); 6600f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett } 6610f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett } 6620f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 6630f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // Increment the table ptr in order to handle the next component. 6640f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // Note that this is the how table is designed: all of nXXX 6650f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // variables are multiples of 3 because there are 3 output 6660f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett // components. 6670f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett ptr++; 6680f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett } 6690f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett} 6700f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 6719ce3a543c92a73e6daca420defc042886b3f2019msarettvoid SkDefaultXform::applyTo8888(SkPMColor* dst, const RGBA32* src, int len) const { 672b39067696ad08a26bbe49b71a71f0546dc42a075msarett while (len-- > 0) { 6730f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett uint8_t r = (*src >> 0) & 0xFF, 6740f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett g = (*src >> 8) & 0xFF, 6750f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett b = (*src >> 16) & 0xFF; 6760f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 6770f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett if (fColorLUT) { 6780f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett float in[3]; 6790f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett float out[3]; 6800f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 6810f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett in[0] = byte_to_float(r); 6820f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett in[1] = byte_to_float(g); 6830f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett in[2] = byte_to_float(b); 6840f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 6850f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett interp_3d_clut(out, in, fColorLUT.get()); 6860f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 6870f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett r = sk_float_round2int(255.0f * clamp_normalized_float(out[0])); 6880f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett g = sk_float_round2int(255.0f * clamp_normalized_float(out[1])); 6890f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett b = sk_float_round2int(255.0f * clamp_normalized_float(out[2])); 6900f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett } 6910f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett 692b39067696ad08a26bbe49b71a71f0546dc42a075msarett // Convert to linear. 693b39067696ad08a26bbe49b71a71f0546dc42a075msarett float srcFloats[3]; 6940f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett srcFloats[0] = fSrcGammaTables[0][r]; 6950f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett srcFloats[1] = fSrcGammaTables[1][g]; 6960f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett srcFloats[2] = fSrcGammaTables[2][b]; 697dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett 698dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett // Convert to dst gamut. 699dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett float dstFloats[3]; 700dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett dstFloats[0] = srcFloats[0] * fSrcToDst.getFloat(0, 0) + 701dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett srcFloats[1] * fSrcToDst.getFloat(1, 0) + 702dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett srcFloats[2] * fSrcToDst.getFloat(2, 0) + fSrcToDst.getFloat(3, 0); 703dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett dstFloats[1] = srcFloats[0] * fSrcToDst.getFloat(0, 1) + 704dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett srcFloats[1] * fSrcToDst.getFloat(1, 1) + 705dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett srcFloats[2] * fSrcToDst.getFloat(2, 1) + fSrcToDst.getFloat(3, 1); 706dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett dstFloats[2] = srcFloats[0] * fSrcToDst.getFloat(0, 2) + 707dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett srcFloats[1] * fSrcToDst.getFloat(1, 2) + 708dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett srcFloats[2] * fSrcToDst.getFloat(2, 2) + fSrcToDst.getFloat(3, 2); 709dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett 710b39067696ad08a26bbe49b71a71f0546dc42a075msarett // Clamp to 0-1. 711b39067696ad08a26bbe49b71a71f0546dc42a075msarett dstFloats[0] = clamp_normalized_float(dstFloats[0]); 712b39067696ad08a26bbe49b71a71f0546dc42a075msarett dstFloats[1] = clamp_normalized_float(dstFloats[1]); 713b39067696ad08a26bbe49b71a71f0546dc42a075msarett dstFloats[2] = clamp_normalized_float(dstFloats[2]); 714b39067696ad08a26bbe49b71a71f0546dc42a075msarett 715dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett // Convert to dst gamma. 7160f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett r = fDstGammaTables[0][sk_float_round2int((kDstGammaTableSize - 1) * dstFloats[0])]; 7170f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett g = fDstGammaTables[1][sk_float_round2int((kDstGammaTableSize - 1) * dstFloats[1])]; 7180f83e0151f757ecd8d55d55ffefef58ecb11a97bmsarett b = fDstGammaTables[2][sk_float_round2int((kDstGammaTableSize - 1) * dstFloats[2])]; 719dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett 720b39067696ad08a26bbe49b71a71f0546dc42a075msarett *dst = SkPackARGB32NoCheck(0xFF, r, g, b); 721dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett 722dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett dst++; 723dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett src++; 724dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett } 725dc27a648d2ff23b2e96232c00c15976c46e1d48dmsarett} 7269ce3a543c92a73e6daca420defc042886b3f2019msarett 7279ce3a543c92a73e6daca420defc042886b3f2019msarettvoid SkDefaultXform::applyToF16(RGBAF16* dst, const RGBA32* src, int len) const { 7289ce3a543c92a73e6daca420defc042886b3f2019msarett // FIXME (msarett): 7299ce3a543c92a73e6daca420defc042886b3f2019msarett // Planning to delete SkDefaultXform. Not going to bother to implement this. 7309ce3a543c92a73e6daca420defc042886b3f2019msarett memset(dst, 0, len * sizeof(RGBAF16)); 7319ce3a543c92a73e6daca420defc042886b3f2019msarett} 732