Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(167)

Side by Side Diff: src/core/SkColorSpaceXform.cpp

Issue 2084673002: Use a table-based implementation of SkDefaultXform (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: quickEquals() Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/core/SkColorSpaceXform.h ('k') | src/core/SkColorSpace_Base.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2016 Google Inc. 2 * Copyright 2016 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkColorPriv.h" 8 #include "SkColorPriv.h"
9 #include "SkColorSpace_Base.h" 9 #include "SkColorSpace_Base.h"
10 #include "SkColorSpaceXform.h" 10 #include "SkColorSpaceXform.h"
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
63 new SkFastXform<SkColorSpace::k2Dot2Curve_GammaNamed , 63 new SkFastXform<SkColorSpace::k2Dot2Curve_GammaNamed ,
64 SkColorSpace::k2Dot2Curve_GammaNamed >(srcToDst)); 64 SkColorSpace::k2Dot2Curve_GammaNamed >(srcToDst));
65 } 65 }
66 break; 66 break;
67 default: 67 default:
68 break; 68 break;
69 } 69 }
70 } 70 }
71 71
72 return std::unique_ptr<SkColorSpaceXform>( 72 return std::unique_ptr<SkColorSpaceXform>(
73 new SkDefaultXform(as_CSB(srcSpace)->gammas(), srcToDst, as_CSB(dstS pace)->gammas())); 73 new SkDefaultXform(srcSpace, srcToDst, dstSpace));
74 } 74 }
75 75
76 //////////////////////////////////////////////////////////////////////////////// /////////////////// 76 //////////////////////////////////////////////////////////////////////////////// ///////////////////
77 77
78 static void build_src_to_dst(float srcToDstArray[12], const SkMatrix44& srcToDst Matrix) { 78 static void build_src_to_dst(float srcToDstArray[12], const SkMatrix44& srcToDst Matrix) {
79 // Build the following row major matrix: 79 // Build the following row major matrix:
80 // rX gX bX 0 80 // rX gX bX 0
81 // rY gY bY 0 81 // rY gY bY 0
82 // rZ gZ bZ 0 82 // rZ gZ bZ 0
83 // Swap R and B if necessary to make sure that we output SkPMColor order. 83 // Swap R and B if necessary to make sure that we output SkPMColor order.
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 139
140 template <> 140 template <>
141 void SkFastXform<SkColorSpace::k2Dot2Curve_GammaNamed, SkColorSpace::k2Dot2Curve _GammaNamed> 141 void SkFastXform<SkColorSpace::k2Dot2Curve_GammaNamed, SkColorSpace::k2Dot2Curve _GammaNamed>
142 ::xform_RGB1_8888(uint32_t* dst, const uint32_t* src, uint32_t len) const 142 ::xform_RGB1_8888(uint32_t* dst, const uint32_t* src, uint32_t len) const
143 { 143 {
144 SkOpts::color_xform_RGB1_2dot2_to_2dot2(dst, src, len, fSrcToDst); 144 SkOpts::color_xform_RGB1_2dot2_to_2dot2(dst, src, len, fSrcToDst);
145 } 145 }
146 146
147 //////////////////////////////////////////////////////////////////////////////// /////////////////// 147 //////////////////////////////////////////////////////////////////////////////// ///////////////////
148 148
149 static inline float byte_to_float(uint8_t v) { 149 extern const float sk_linear_from_srgb[256] = {
150 return ((float) v) * (1.0f / 255.0f); 150 0.000000000000000000f, 0.000303526983548838f, 0.000607053967097675f, 0.0 00910580950646513f,
151 0.001214107934195350f, 0.001517634917744190f, 0.001821161901293030f, 0.0 02124688884841860f,
152 0.002428215868390700f, 0.002731742851939540f, 0.003034518678424960f, 0.0 03346535763899160f,
153 0.003676507324047440f, 0.004024717018496310f, 0.004391442037410290f, 0.0 04776953480693730f,
154 0.005181516702338390f, 0.005605391624202720f, 0.006048833022857060f, 0.0 06512090792594470f,
155 0.006995410187265390f, 0.007499032043226180f, 0.008023192985384990f, 0.0 08568125618069310f,
156 0.009134058702220790f, 0.009721217320237850f, 0.010329823029626900f, 0.0 10960094006488200f,
157 0.011612245179743900f, 0.012286488356915900f, 0.012983032342173000f, 0.0 13702083047289700f,
158 0.014443843596092500f, 0.015208514422912700f, 0.015996293365509600f, 0.0 16807375752887400f,
159 0.017641954488384100f, 0.018500220128379700f, 0.019382360956935700f, 0.0 20288563056652400f,
160 0.021219010376003600f, 0.022173884793387400f, 0.023153366178110400f, 0.0 24157632448504800f,
161 0.025186859627361600f, 0.026241221894849900f, 0.027320891639074900f, 0.0 28426039504420800f,
162 0.029556834437808800f, 0.030713443732993600f, 0.031896033073011500f, 0.0 33104766570885100f,
163 0.034339806808682200f, 0.035601314875020300f, 0.036889450401100000f, 0.0 38204371595346500f,
164 0.039546235276732800f, 0.040915196906853200f, 0.042311410620809700f, 0.0 43735029256973500f,
165 0.045186204385675500f, 0.046665086336880100f, 0.048171824226889400f, 0.0 49706565984127200f,
166 0.051269458374043200f, 0.052860647023180200f, 0.054480276442442400f, 0.0 56128490049600100f,
167 0.057805430191067200f, 0.059511238162981200f, 0.061246054231617600f, 0.0 63010017653167700f,
168 0.064803266692905800f, 0.066625938643772900f, 0.068478169844400200f, 0.0 70360095696595900f,
169 0.072271850682317500f, 0.074213568380149600f, 0.076185381481307900f, 0.0 78187421805186300f,
170 0.080219820314468300f, 0.082282707129814800f, 0.084376211544148800f, 0.0 86500462036549800f,
171 0.088655586285772900f, 0.090841711183407700f, 0.093058962846687500f, 0.0 95307466630964700f,
172 0.097587347141862500f, 0.099898728247113900f, 0.102241733088101000f, 0.1 04616484091104000f,
173 0.107023102978268000f, 0.109461710778299000f, 0.111932427836906000f, 0.1 14435373826974000f,
174 0.116970667758511000f, 0.119538427988346000f, 0.122138772229602000f, 0.1 24771817560950000f,
175 0.127437680435647000f, 0.130136476690364000f, 0.132868321553818000f, 0.1 35633329655206000f,
176 0.138431615032452000f, 0.141263291140272000f, 0.144128470858058000f, 0.1 47027266497595000f,
177 0.149959789810609000f, 0.152926151996150000f, 0.155926463707827000f, 0.1 58960835060880000f,
178 0.162029375639111000f, 0.165132194501668000f, 0.168269400189691000f, 0.1 71441100732823000f,
179 0.174647403655585000f, 0.177888415983629000f, 0.181164244249860000f, 0.1 84474994500441000f,
180 0.187820772300678000f, 0.191201682740791000f, 0.194617830441576000f, 0.1 98069319559949000f,
181 0.201556253794397000f, 0.205078736390317000f, 0.208636870145256000f, 0.2 12230757414055000f,
182 0.215860500113899000f, 0.219526199729269000f, 0.223227957316809000f, 0.2 26965873510098000f,
183 0.230740048524349000f, 0.234550582161005000f, 0.238397573812271000f, 0.2 42281122465555000f,
184 0.246201326707835000f, 0.250158284729953000f, 0.254152094330827000f, 0.2 58182852921596000f,
185 0.262250657529696000f, 0.266355604802862000f, 0.270497791013066000f, 0.2 74677312060385000f,
186 0.278894263476810000f, 0.283148740429992000f, 0.287440837726918000f, 0.2 91770649817536000f,
187 0.296138270798321000f, 0.300543794415777000f, 0.304987314069886000f, 0.3 09468922817509000f,
188 0.313988713375718000f, 0.318546778125092000f, 0.323143209112951000f, 0.3 27778098056542000f,
189 0.332451536346179000f, 0.337163615048330000f, 0.341914424908661000f, 0.3 46704056355030000f,
190 0.351532599500439000f, 0.356400144145944000f, 0.361306779783510000f, 0.3 66252595598840000f,
191 0.371237680474149000f, 0.376262122990906000f, 0.381326011432530000f, 0.3 86429433787049000f,
192 0.391572477749723000f, 0.396755230725627000f, 0.401977779832196000f, 0.4 07240211901737000f,
193 0.412542613483904000f, 0.417885070848138000f, 0.423267669986072000f, 0.4 28690496613907000f,
194 0.434153636174749000f, 0.439657173840919000f, 0.445201194516228000f, 0.4 50785782838223000f,
195 0.456411023180405000f, 0.462076999654407000f, 0.467783796112159000f, 0.4 73531496148010000f,
196 0.479320183100827000f, 0.485149940056070000f, 0.491020849847836000f, 0.4 96932995060870000f,
197 0.502886458032569000f, 0.508881320854934000f, 0.514917665376521000f, 0.5 20995573204354000f,
198 0.527115125705813000f, 0.533276404010505000f, 0.539479489012107000f, 0.5 45724461370187000f,
199 0.552011401512000000f, 0.558340389634268000f, 0.564711505704929000f, 0.5 71124829464873000f,
200 0.577580440429651000f, 0.584078417891164000f, 0.590618840919337000f, 0.5 97201788363763000f,
201 0.603827338855338000f, 0.610495570807865000f, 0.617206562419651000f, 0.6 23960391675076000f,
202 0.630757136346147000f, 0.637596873994033000f, 0.644479681970582000f, 0.6 51405637419824000f,
203 0.658374817279448000f, 0.665387298282272000f, 0.672443156957688000f, 0.6 79542469633094000f,
204 0.686685312435314000f, 0.693871761291990000f, 0.701101891932973000f, 0.7 08375779891687000f,
205 0.715693500506481000f, 0.723055128921969000f, 0.730460740090354000f, 0.7 37910408772731000f,
206 0.745404209540387000f, 0.752942216776078000f, 0.760524504675292000f, 0.7 68151147247507000f,
207 0.775822218317423000f, 0.783537791526194000f, 0.791297940332630000f, 0.7 99102738014409000f,
208 0.806952257669252000f, 0.814846572216101000f, 0.822785754396284000f, 0.8 30769876774655000f,
209 0.838799011740740000f, 0.846873231509858000f, 0.854992608124234000f, 0.8 63157213454102000f,
210 0.871367119198797000f, 0.879622396887832000f, 0.887923117881966000f, 0.8 96269353374266000f,
211 0.904661174391149000f, 0.913098651793419000f, 0.921581856277295000f, 0.9 30110858375424000f,
212 0.938685728457888000f, 0.947306536733200000f, 0.955973353249286000f, 0.9 64686247894465000f,
213 0.973445290398413000f, 0.982250550333117000f, 0.991102097113830000f, 1.0 00000000000000000f,
214 };
215
216 extern const float sk_linear_from_2dot2[256] = {
217 0.000000000000000000f, 0.000005077051900662f, 0.000023328004666099f, 0.0 00056921765712193f,
218 0.000107187362341244f, 0.000175123977503027f, 0.000261543754548491f, 0.0 00367136269815943f,
219 0.000492503787191433f, 0.000638182842167022f, 0.000804658499513058f, 0.0 00992374304074325f,
220 0.001201739522438400f, 0.001433134589671860f, 0.001686915316789280f, 0.0 01963416213396470f,
221 0.002262953160706430f, 0.002585825596234170f, 0.002932318323938360f, 0.0 03302703032003640f,
222 0.003697239578900130f, 0.004116177093282750f, 0.004559754922526020f, 0.0 05028203456855540f,
223 0.005521744850239660f, 0.006040593654849810f, 0.006584957382581690f, 0.0 07155037004573030f,
224 0.007751027397660610f, 0.008373117745148580f, 0.009021491898012130f, 0.0 09696328701658230f,
225 0.010397802292555300f, 0.011126082368383200f, 0.011881334434813700f, 0.0 12663720031582100f,
226 0.013473396940142600f, 0.014310519374884100f, 0.015175238159625200f, 0.0 16067700890886900f,
227 0.016988052089250000f, 0.017936433339950200f, 0.018912983423721500f, 0.0 19917838438785700f,
228 0.020951131914781100f, 0.022012994919336500f, 0.023103556157921400f, 0.0 24222942067534200f,
229 0.025371276904734600f, 0.026548682828472900f, 0.027755279978126000f, 0.0 28991186547107800f,
230 0.030256518852388700f, 0.031551391400226400f, 0.032875916948383800f, 0.0 34230206565082000f,
231 0.035614369684918800f, 0.037028514161960200f, 0.038472746320194600f, 0.0 39947171001525600f,
232 0.041451891611462500f, 0.042987010162657100f, 0.044552627316421400f, 0.0 46148842422351000f,
233 0.047775753556170600f, 0.049433457555908000f, 0.051122050056493400f, 0.0 52841625522879000f,
234 0.054592277281760300f, 0.056374097551979800f, 0.058187177473685400f, 0.0 60031607136313200f,
235 0.061907475605455800f, 0.063814870948677200f, 0.065753880260330100f, 0.0 67724589685424300f,
236 0.069727084442598800f, 0.071761448846239100f, 0.073827766327784600f, 0.0 75926119456264800f,
237 0.078056589958101900f, 0.080219258736215100f, 0.082414205888459200f, 0.0 84641510725429500f,
238 0.086901251787660300f, 0.089193506862247800f, 0.091518352998919500f, 0.0 93875866525577800f,
239 0.096266123063339700f, 0.098689197541094500f, 0.101145164209600000f, 0.1 03634096655137000f,
240 0.106156067812744000f, 0.108711149979039000f, 0.111299414824660000f, 0.1 13920933406333000f,
241 0.116575776178572000f, 0.119264013005047000f, 0.121985713169619000f, 0.1 24740945387051000f,
242 0.127529777813422000f, 0.130352278056244000f, 0.133208513184300000f, 0.1 36098549737202000f,
243 0.139022453734703000f, 0.141980290685736000f, 0.144972125597231000f, 0.1 47998022982685000f,
244 0.151058046870511000f, 0.154152260812165000f, 0.157280727890073000f, 0.1 60443510725344000f,
245 0.163640671485290000f, 0.166872271890766000f, 0.170138373223312000f, 0.1 73439036332135000f,
246 0.176774321640903000f, 0.180144289154390000f, 0.183548998464951000f, 0.1 86988508758844000f,
247 0.190462878822409000f, 0.193972167048093000f, 0.197516431440340000f, 0.2 01095729621346000f,
248 0.204710118836677000f, 0.208359655960767000f, 0.212044397502288000f, 0.2 15764399609395000f,
249 0.219519718074868000f, 0.223310408341127000f, 0.227136525505149000f, 0.2 30998124323267000f,
250 0.234895259215880000f, 0.238827984272048000f, 0.242796353254002000f, 0.2 46800419601550000f,
251 0.250840236436400000f, 0.254915856566385000f, 0.259027332489606000f, 0.2 63174716398492000f,
252 0.267358060183772000f, 0.271577415438375000f, 0.275832833461245000f, 0.2 80124365261085000f,
253 0.284452061560024000f, 0.288815972797219000f, 0.293216149132375000f, 0.2 97652640449211000f,
254 0.302125496358853000f, 0.306634766203158000f, 0.311180499057984000f, 0.3 15762743736397000f,
255 0.320381548791810000f, 0.325036962521076000f, 0.329729032967515000f, 0.3 34457807923889000f,
256 0.339223334935327000f, 0.344025661302187000f, 0.348864834082879000f, 0.3 53740900096629000f,
257 0.358653905926199000f, 0.363603897920553000f, 0.368590922197487000f, 0.3 73615024646202000f,
258 0.378676250929840000f, 0.383774646487975000f, 0.388910256539059000f, 0.3 94083126082829000f,
259 0.399293299902674000f, 0.404540822567962000f, 0.409825738436323000f, 0.4 15148091655907000f,
260 0.420507926167587000f, 0.425905285707146000f, 0.431340213807410000f, 0.4 36812753800359000f,
261 0.442322948819202000f, 0.447870841800410000f, 0.453456475485731000f, 0.4 59079892424160000f,
262 0.464741134973889000f, 0.470440245304218000f, 0.476177265397440000f, 0.4 81952237050698000f,
263 0.487765201877811000f, 0.493616201311074000f, 0.499505276603030000f, 0.5 05432468828216000f,
264 0.511397818884880000f, 0.517401367496673000f, 0.523443155214325000f, 0.5 29523222417277000f,
265 0.535641609315311000f, 0.541798355950137000f, 0.547993502196972000f, 0.5 54227087766085000f,
266 0.560499152204328000f, 0.566809734896638000f, 0.573158875067523000f, 0.5 79546611782525000f,
267 0.585972983949661000f, 0.592438030320847000f, 0.598941789493296000f, 0.6 05484299910907000f,
268 0.612065599865624000f, 0.618685727498780000f, 0.625344720802427000f, 0.6 32042617620641000f,
269 0.638779455650817000f, 0.645555272444935000f, 0.652370105410821000f, 0.6 59223991813387000f,
270 0.666116968775851000f, 0.673049073280942000f, 0.680020342172095000f, 0.6 87030812154625000f,
271 0.694080519796882000f, 0.701169501531402000f, 0.708297793656032000f, 0.7 15465432335048000f,
272 0.722672453600255000f, 0.729918893352071000f, 0.737204787360605000f, 0.7 44530171266715000f,
273 0.751895080583051000f, 0.759299550695091000f, 0.766743616862161000f, 0.7 74227314218442000f,
274 0.781750677773962000f, 0.789313742415586000f, 0.796916542907978000f, 0.8 04559113894567000f,
275 0.812241489898490000f, 0.819963705323528000f, 0.827725794455034000f, 0.8 35527791460841000f,
276 0.843369730392169000f, 0.851251645184515000f, 0.859173569658532000f, 0.8 67135537520905000f,
277 0.875137582365205000f, 0.883179737672745000f, 0.891262036813419000f, 0.8 99384513046529000f,
278 0.907547199521614000f, 0.915750129279253000f, 0.923993335251873000f, 0.9 32276850264543000f,
279 0.940600707035753000f, 0.948964938178195000f, 0.957369576199527000f, 0.9 65814653503130000f,
280 0.974300202388861000f, 0.982826255053791000f, 0.991392843592940000f, 1.0 00000000000000000f,
281 };
282
283 static void build_table_linear_from_gamma(float* outTable, float exponent) {
284 for (float x = 0.0f; x <= 1.0f; x += (1.0f/255.0f)) {
285 *outTable++ = powf(x, exponent);
286 }
151 } 287 }
152 288
289 // Interpolating lookup in a variably sized table.
290 static float interp_lut(float input, const float* table, int tableSize) {
291 float index = input * (tableSize - 1);
292 float diff = index - sk_float_floor2int(index);
293 return table[(int) sk_float_floor2int(index)] * (1.0f - diff) +
294 table[(int) sk_float_ceil2int(index)] * diff;
295 }
296
297 // outTable is always 256 entries, inTable may be larger or smaller.
298 static void build_table_linear_from_gamma(float* outTable, const float* inTable,
299 int inTableSize) {
300 if (256 == inTableSize) {
301 memcpy(outTable, inTable, sizeof(float) * 256);
302 return;
303 }
304
305 for (float x = 0.0f; x <= 1.0f; x += (1.0f/255.0f)) {
306 *outTable++ = interp_lut(x, inTable, inTableSize);
307 }
308 }
309
310 static void build_table_linear_from_gamma(float* outTable, float g, float a, flo at b, float c,
311 float d, float e, float f) {
312 // Y = (aX + b)^g + c for X >= d
313 // Y = eX + f otherwise
314 for (float x = 0.0f; x <= 1.0f; x += (1.0f/255.0f)) {
315 if (x >= d) {
316 *outTable++ = powf(a * x + b, g) + c;
317 } else {
318 *outTable++ = e * x + f;
319 }
320 }
321 }
322
323 static constexpr uint8_t linear_to_srgb[1024] = {
324 0, 3, 6, 10, 13, 15, 18, 20, 22, 23, 25, 27, 28, 30, 3 1, 32, 34, 35,
325 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 4 9, 50, 51, 52,
326 53, 53, 54, 55, 56, 56, 57, 58, 58, 59, 60, 61, 61, 62, 6 2, 63, 64, 64,
327 65, 66, 66, 67, 67, 68, 68, 69, 70, 70, 71, 71, 72, 72, 7 3, 73, 74, 74,
328 75, 76, 76, 77, 77, 78, 78, 79, 79, 79, 80, 80, 81, 81, 8 2, 82, 83, 83,
329 84, 84, 85, 85, 85, 86, 86, 87, 87, 88, 88, 88, 89, 89, 9 0, 90, 91, 91,
330 91, 92, 92, 93, 93, 93, 94, 94, 95, 95, 95, 96, 96, 97, 9 7, 97, 98, 98,
331 98, 99, 99, 99, 100, 100, 101, 101, 101, 102, 102, 102, 103, 103, 10 3, 104, 104, 104,
332 105, 105, 106, 106, 106, 107, 107, 107, 108, 108, 108, 109, 109, 109, 11 0, 110, 110, 110,
333 111, 111, 111, 112, 112, 112, 113, 113, 113, 114, 114, 114, 115, 115, 11 5, 115, 116, 116,
334 116, 117, 117, 117, 118, 118, 118, 118, 119, 119, 119, 120, 120, 120, 12 1, 121, 121, 121,
335 122, 122, 122, 123, 123, 123, 123, 124, 124, 124, 125, 125, 125, 125, 12 6, 126, 126, 126,
336 127, 127, 127, 128, 128, 128, 128, 129, 129, 129, 129, 130, 130, 130, 13 0, 131, 131, 131,
337 131, 132, 132, 132, 133, 133, 133, 133, 134, 134, 134, 134, 135, 135, 13 5, 135, 136, 136,
338 136, 136, 137, 137, 137, 137, 138, 138, 138, 138, 138, 139, 139, 139, 13 9, 140, 140, 140,
339 140, 141, 141, 141, 141, 142, 142, 142, 142, 143, 143, 143, 143, 143, 14 4, 144, 144, 144,
340 145, 145, 145, 145, 146, 146, 146, 146, 146, 147, 147, 147, 147, 148, 14 8, 148, 148, 148,
341 149, 149, 149, 149, 150, 150, 150, 150, 150, 151, 151, 151, 151, 152, 15 2, 152, 152, 152,
342 153, 153, 153, 153, 153, 154, 154, 154, 154, 155, 155, 155, 155, 155, 15 6, 156, 156, 156,
343 156, 157, 157, 157, 157, 157, 158, 158, 158, 158, 158, 159, 159, 159, 15 9, 159, 160, 160,
344 160, 160, 160, 161, 161, 161, 161, 161, 162, 162, 162, 162, 162, 163, 16 3, 163, 163, 163,
345 164, 164, 164, 164, 164, 165, 165, 165, 165, 165, 166, 166, 166, 166, 16 6, 167, 167, 167,
346 167, 167, 168, 168, 168, 168, 168, 168, 169, 169, 169, 169, 169, 170, 17 0, 170, 170, 170,
347 171, 171, 171, 171, 171, 171, 172, 172, 172, 172, 172, 173, 173, 173, 17 3, 173, 173, 174,
348 174, 174, 174, 174, 175, 175, 175, 175, 175, 175, 176, 176, 176, 176, 17 6, 177, 177, 177,
349 177, 177, 177, 178, 178, 178, 178, 178, 178, 179, 179, 179, 179, 179, 17 9, 180, 180, 180,
350 180, 180, 181, 181, 181, 181, 181, 181, 182, 182, 182, 182, 182, 182, 18 3, 183, 183, 183,
351 183, 183, 184, 184, 184, 184, 184, 184, 185, 185, 185, 185, 185, 185, 18 6, 186, 186, 186,
352 186, 186, 187, 187, 187, 187, 187, 187, 188, 188, 188, 188, 188, 188, 18 9, 189, 189, 189,
353 189, 189, 190, 190, 190, 190, 190, 190, 191, 191, 191, 191, 191, 191, 19 1, 192, 192, 192,
354 192, 192, 192, 193, 193, 193, 193, 193, 193, 194, 194, 194, 194, 194, 19 4, 194, 195, 195,
355 195, 195, 195, 195, 196, 196, 196, 196, 196, 196, 197, 197, 197, 197, 19 7, 197, 197, 198,
356 198, 198, 198, 198, 198, 199, 199, 199, 199, 199, 199, 199, 200, 200, 20 0, 200, 200, 200,
357 200, 201, 201, 201, 201, 201, 201, 202, 202, 202, 202, 202, 202, 202, 20 3, 203, 203, 203,
358 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 205, 205, 205, 205, 20 5, 205, 206, 206,
359 206, 206, 206, 206, 206, 207, 207, 207, 207, 207, 207, 207, 208, 208, 20 8, 208, 208, 208,
360 208, 209, 209, 209, 209, 209, 209, 209, 210, 210, 210, 210, 210, 210, 21 0, 211, 211, 211,
361 211, 211, 211, 211, 212, 212, 212, 212, 212, 212, 212, 212, 213, 213, 21 3, 213, 213, 213,
362 213, 214, 214, 214, 214, 214, 214, 214, 215, 215, 215, 215, 215, 215, 21 5, 216, 216, 216,
363 216, 216, 216, 216, 216, 217, 217, 217, 217, 217, 217, 217, 218, 218, 21 8, 218, 218, 218,
364 218, 219, 219, 219, 219, 219, 219, 219, 219, 220, 220, 220, 220, 220, 22 0, 220, 221, 221,
365 221, 221, 221, 221, 221, 221, 222, 222, 222, 222, 222, 222, 222, 222, 22 3, 223, 223, 223,
366 223, 223, 223, 224, 224, 224, 224, 224, 224, 224, 224, 225, 225, 225, 22 5, 225, 225, 225,
367 225, 226, 226, 226, 226, 226, 226, 226, 227, 227, 227, 227, 227, 227, 22 7, 227, 228, 228,
368 228, 228, 228, 228, 228, 228, 229, 229, 229, 229, 229, 229, 229, 229, 23 0, 230, 230, 230,
369 230, 230, 230, 230, 231, 231, 231, 231, 231, 231, 231, 231, 232, 232, 23 2, 232, 232, 232,
370 232, 232, 233, 233, 233, 233, 233, 233, 233, 233, 234, 234, 234, 234, 23 4, 234, 234, 234,
371 235, 235, 235, 235, 235, 235, 235, 235, 236, 236, 236, 236, 236, 236, 23 6, 236, 236, 237,
372 237, 237, 237, 237, 237, 237, 237, 238, 238, 238, 238, 238, 238, 238, 23 8, 239, 239, 239,
373 239, 239, 239, 239, 239, 239, 240, 240, 240, 240, 240, 240, 240, 240, 24 1, 241, 241, 241,
374 241, 241, 241, 241, 241, 242, 242, 242, 242, 242, 242, 242, 242, 243, 24 3, 243, 243, 243,
375 243, 243, 243, 243, 244, 244, 244, 244, 244, 244, 244, 244, 245, 245, 24 5, 245, 245, 245,
376 245, 245, 245, 246, 246, 246, 246, 246, 246, 246, 246, 246, 247, 247, 24 7, 247, 247, 247,
377 247, 247, 248, 248, 248, 248, 248, 248, 248, 248, 248, 249, 249, 249, 24 9, 249, 249, 249,
378 249, 249, 250, 250, 250, 250, 250, 250, 250, 250, 250, 251, 251, 251, 25 1, 251, 251, 251,
379 251, 251, 252, 252, 252, 252, 252, 252, 252, 252, 252, 253, 253, 253, 25 3, 253, 253, 253,
380 253, 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 255, 255, 255, 25 5, 255
381 };
382
383 static constexpr uint8_t linear_to_2dot2[1024] = {
384 0, 11, 15, 18, 21, 23, 25, 26, 28, 30, 31, 32, 34, 35, 3 6, 37, 39, 40,
385 41, 42, 43, 44, 45, 45, 46, 47, 48, 49, 50, 50, 51, 52, 5 3, 54, 54, 55,
386 56, 56, 57, 58, 58, 59, 60, 60, 61, 62, 62, 63, 63, 64, 6 5, 65, 66, 66,
387 67, 68, 68, 69, 69, 70, 70, 71, 71, 72, 72, 73, 73, 74, 7 4, 75, 75, 76,
388 76, 77, 77, 78, 78, 79, 79, 80, 80, 81, 81, 81, 82, 82, 8 3, 83, 84, 84,
389 84, 85, 85, 86, 86, 87, 87, 87, 88, 88, 89, 89, 89, 90, 9 0, 91, 91, 91,
390 92, 92, 93, 93, 93, 94, 94, 94, 95, 95, 96, 96, 96, 97, 9 7, 97, 98, 98,
391 98, 99, 99, 99, 100, 100, 101, 101, 101, 102, 102, 102, 103, 103, 10 3, 104, 104, 104,
392 105, 105, 105, 106, 106, 106, 107, 107, 107, 108, 108, 108, 108, 109, 10 9, 109, 110, 110,
393 110, 111, 111, 111, 112, 112, 112, 112, 113, 113, 113, 114, 114, 114, 11 5, 115, 115, 115,
394 116, 116, 116, 117, 117, 117, 117, 118, 118, 118, 119, 119, 119, 119, 12 0, 120, 120, 121,
395 121, 121, 121, 122, 122, 122, 123, 123, 123, 123, 124, 124, 124, 124, 12 5, 125, 125, 125,
396 126, 126, 126, 127, 127, 127, 127, 128, 128, 128, 128, 129, 129, 129, 12 9, 130, 130, 130,
397 130, 131, 131, 131, 131, 132, 132, 132, 132, 133, 133, 133, 133, 134, 13 4, 134, 134, 135,
398 135, 135, 135, 136, 136, 136, 136, 137, 137, 137, 137, 138, 138, 138, 13 8, 138, 139, 139,
399 139, 139, 140, 140, 140, 140, 141, 141, 141, 141, 142, 142, 142, 142, 14 2, 143, 143, 143,
400 143, 144, 144, 144, 144, 144, 145, 145, 145, 145, 146, 146, 146, 146, 14 6, 147, 147, 147,
401 147, 148, 148, 148, 148, 148, 149, 149, 149, 149, 149, 150, 150, 150, 15 0, 151, 151, 151,
402 151, 151, 152, 152, 152, 152, 152, 153, 153, 153, 153, 154, 154, 154, 15 4, 154, 155, 155,
403 155, 155, 155, 156, 156, 156, 156, 156, 157, 157, 157, 157, 157, 158, 15 8, 158, 158, 158,
404 159, 159, 159, 159, 159, 160, 160, 160, 160, 160, 161, 161, 161, 161, 16 1, 162, 162, 162,
405 162, 162, 163, 163, 163, 163, 163, 164, 164, 164, 164, 164, 165, 165, 16 5, 165, 165, 165,
406 166, 166, 166, 166, 166, 167, 167, 167, 167, 167, 168, 168, 168, 168, 16 8, 168, 169, 169,
407 169, 169, 169, 170, 170, 170, 170, 170, 171, 171, 171, 171, 171, 171, 17 2, 172, 172, 172,
408 172, 173, 173, 173, 173, 173, 173, 174, 174, 174, 174, 174, 174, 175, 17 5, 175, 175, 175,
409 176, 176, 176, 176, 176, 176, 177, 177, 177, 177, 177, 177, 178, 178, 17 8, 178, 178, 179,
410 179, 179, 179, 179, 179, 180, 180, 180, 180, 180, 180, 181, 181, 181, 18 1, 181, 181, 182,
411 182, 182, 182, 182, 182, 183, 183, 183, 183, 183, 183, 184, 184, 184, 18 4, 184, 185, 185,
412 185, 185, 185, 185, 186, 186, 186, 186, 186, 186, 186, 187, 187, 187, 18 7, 187, 187, 188,
413 188, 188, 188, 188, 188, 189, 189, 189, 189, 189, 189, 190, 190, 190, 19 0, 190, 190, 191,
414 191, 191, 191, 191, 191, 192, 192, 192, 192, 192, 192, 192, 193, 193, 19 3, 193, 193, 193,
415 194, 194, 194, 194, 194, 194, 195, 195, 195, 195, 195, 195, 195, 196, 19 6, 196, 196, 196,
416 196, 197, 197, 197, 197, 197, 197, 197, 198, 198, 198, 198, 198, 198, 19 9, 199, 199, 199,
417 199, 199, 199, 200, 200, 200, 200, 200, 200, 201, 201, 201, 201, 201, 20 1, 201, 202, 202,
418 202, 202, 202, 202, 202, 203, 203, 203, 203, 203, 203, 204, 204, 204, 20 4, 204, 204, 204,
419 205, 205, 205, 205, 205, 205, 205, 206, 206, 206, 206, 206, 206, 206, 20 7, 207, 207, 207,
420 207, 207, 207, 208, 208, 208, 208, 208, 208, 209, 209, 209, 209, 209, 20 9, 209, 210, 210,
421 210, 210, 210, 210, 210, 211, 211, 211, 211, 211, 211, 211, 212, 212, 21 2, 212, 212, 212,
422 212, 213, 213, 213, 213, 213, 213, 213, 213, 214, 214, 214, 214, 214, 21 4, 214, 215, 215,
423 215, 215, 215, 215, 215, 216, 216, 216, 216, 216, 216, 216, 217, 217, 21 7, 217, 217, 217,
424 217, 218, 218, 218, 218, 218, 218, 218, 218, 219, 219, 219, 219, 219, 21 9, 219, 220, 220,
425 220, 220, 220, 220, 220, 221, 221, 221, 221, 221, 221, 221, 221, 222, 22 2, 222, 222, 222,
426 222, 222, 223, 223, 223, 223, 223, 223, 223, 223, 224, 224, 224, 224, 22 4, 224, 224, 225,
427 225, 225, 225, 225, 225, 225, 225, 226, 226, 226, 226, 226, 226, 226, 22 6, 227, 227, 227,
428 227, 227, 227, 227, 228, 228, 228, 228, 228, 228, 228, 228, 229, 229, 22 9, 229, 229, 229,
429 229, 229, 230, 230, 230, 230, 230, 230, 230, 230, 231, 231, 231, 231, 23 1, 231, 231, 232,
430 232, 232, 232, 232, 232, 232, 232, 233, 233, 233, 233, 233, 233, 233, 23 3, 234, 234, 234,
431 234, 234, 234, 234, 234, 235, 235, 235, 235, 235, 235, 235, 235, 236, 23 6, 236, 236, 236,
432 236, 236, 236, 237, 237, 237, 237, 237, 237, 237, 237, 238, 238, 238, 23 8, 238, 238, 238,
433 238, 238, 239, 239, 239, 239, 239, 239, 239, 239, 240, 240, 240, 240, 24 0, 240, 240, 240,
434 241, 241, 241, 241, 241, 241, 241, 241, 242, 242, 242, 242, 242, 242, 24 2, 242, 243, 243,
435 243, 243, 243, 243, 243, 243, 243, 244, 244, 244, 244, 244, 244, 244, 24 4, 245, 245, 245,
436 245, 245, 245, 245, 245, 245, 246, 246, 246, 246, 246, 246, 246, 246, 24 7, 247, 247, 247,
437 247, 247, 247, 247, 248, 248, 248, 248, 248, 248, 248, 248, 248, 249, 24 9, 249, 249, 249,
438 249, 249, 249, 249, 250, 250, 250, 250, 250, 250, 250, 250, 251, 251, 25 1, 251, 251, 251,
439 251, 251, 251, 252, 252, 252, 252, 252, 252, 252, 252, 252, 253, 253, 25 3, 253, 253, 253,
440 253, 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 255, 255, 255, 25 5, 255,
441 };
442
153 // Expand range from 0-1 to 0-255, then convert. 443 // Expand range from 0-1 to 0-255, then convert.
154 static inline uint8_t clamp_normalized_float_to_byte(float v) { 444 static uint8_t clamp_normalized_float_to_byte(float v) {
155 // The ordering of the logic is a little strange here in order 445 // The ordering of the logic is a little strange here in order
156 // to make sure we convert NaNs to 0. 446 // to make sure we convert NaNs to 0.
157 v = v * 255.0f; 447 v = v * 255.0f;
158 if (v >= 254.5f) { 448 if (v >= 254.5f) {
159 return 255; 449 return 255;
160 } else if (v >= 0.5f) { 450 } else if (v >= 0.5f) {
161 return (uint8_t) (v + 0.5f); 451 return (uint8_t) (v + 0.5f);
162 } else { 452 } else {
163 return 0; 453 return 0;
164 } 454 }
165 } 455 }
166 456
167 // Interpolating lookup in a variably sized table. 457 static void build_table_linear_to_gamma(uint8_t* outTable, int outTableSize, flo at exponent) {
168 static inline float interp_lut(uint8_t byte, float* table, size_t tableSize) { 458 float toGammaExp = 1.0f / exponent;
169 float index = byte_to_float(byte) * (tableSize - 1); 459
170 float diff = index - sk_float_floor2int(index); 460 for (int i = 0; i < outTableSize; i++) {
171 return table[(int) sk_float_floor2int(index)] * (1.0f - diff) + 461 float x = ((float) i) * (1.0f / ((float) (outTableSize - 1)));
172 table[(int) sk_float_ceil2int(index)] * diff; 462 outTable[i] = clamp_normalized_float_to_byte(powf(x, toGammaExp));
463 }
173 } 464 }
174 465
175 // Inverse table lookup. Ex: what index corresponds to the input value? This w ill 466 // Inverse table lookup. Ex: what index corresponds to the input value? This w ill
176 // have strange results when the table is non-increasing. But any sane gamma 467 // have strange results when the table is non-increasing. But any sane gamma
177 // function will be increasing. 468 // function will be increasing.
178 // FIXME (msarett): 469 static float inverse_interp_lut(float input, float* table, int tableSize) {
179 // This is a placeholder implementation for inverting table gammas. First, I ne ed to
180 // verify if there are actually destination profiles that require this functiona lity.
181 // Next, there are certainly faster and more robust approaches to solving this p roblem.
182 // The LUT based approach in QCMS would be a good place to start.
183 static inline float interp_lut_inv(float input, float* table, size_t tableSize) {
184 if (input <= table[0]) { 470 if (input <= table[0]) {
185 return table[0]; 471 return table[0];
186 } else if (input >= table[tableSize - 1]) { 472 } else if (input >= table[tableSize - 1]) {
187 return 1.0f; 473 return 1.0f;
188 } 474 }
189 475
190 for (uint32_t i = 1; i < tableSize; i++) { 476 for (int i = 1; i < tableSize; i++) {
191 if (table[i] >= input) { 477 if (table[i] >= input) {
192 // We are guaranteed that input is greater than table[i - 1]. 478 // We are guaranteed that input is greater than table[i - 1].
193 float diff = input - table[i - 1]; 479 float diff = input - table[i - 1];
194 float distance = table[i] - table[i - 1]; 480 float distance = table[i] - table[i - 1];
195 float index = (i - 1) + diff / distance; 481 float index = (i - 1) + diff / distance;
196 return index / (tableSize - 1); 482 return index / (tableSize - 1);
197 } 483 }
198 } 484 }
199 485
200 // Should be unreachable, since we'll return before the loop if input is 486 // Should be unreachable, since we'll return before the loop if input is
201 // larger than the last entry. 487 // larger than the last entry.
202 SkASSERT(false); 488 SkASSERT(false);
203 return 0.0f; 489 return 0.0f;
204 } 490 }
205 491
206 SkDefaultXform::SkDefaultXform(const sk_sp<SkGammas>& srcGammas, const SkMatrix4 4& srcToDst, 492 static void build_table_linear_to_gamma(uint8_t* outTable, int outTableSize, flo at* inTable,
207 const sk_sp<SkGammas>& dstGammas) 493 int inTableSize) {
208 : fSrcGammas(srcGammas) 494 for (int i = 0; i < outTableSize; i++) {
209 , fSrcToDst(srcToDst) 495 float x = ((float) i) * (1.0f / ((float) (outTableSize - 1)));
210 , fDstGammas(dstGammas) 496 float y = inverse_interp_lut(x, inTable, inTableSize);
211 {} 497 outTable[i] = clamp_normalized_float_to_byte(y);
498 }
499 }
500
501 static float inverse_parametric(float x, float g, float a, float b, float c, flo at d, float e,
502 float f) {
503 // We need to take the inverse of the following piecewise function.
504 // Y = (aX + b)^g + c for X >= d
505 // Y = eX + f otherwise
506
507 // Assume that the gamma function is continuous, or this won't make much sen se anyway.
508 // Plug in |d| to the first equation to calculate the new piecewise interval .
509 // Then simply use the inverse of the original functions.
510 float interval = e * d + f;
511 if (x < interval) {
512 // X = (Y - F) / E
513 if (0.0f == e) {
514 // The gamma curve for this segment is constant, so the inverse is u ndefined.
515 // Since this is the lower segment, guess zero.
516 return 0.0f;
517 }
518
519 return (x - f) / e;
520 }
521
522 // X = ((Y - C)^(1 / G) - B) / A
523 if (0.0f == a || 0.0f == g) {
524 // The gamma curve for this segment is constant, so the inverse is undef ined.
525 // Since this is the upper segment, guess one.
526 return 1.0f;
527 }
528
529 return (powf(x - c, 1.0f / g) - b) / a;
530 }
531
532 static void build_table_linear_to_gamma(uint8_t* outTable, int outTableSize, flo at g, float a,
533 float b, float c, float d, float e, floa t f) {
534 for (int i = 0; i < outTableSize; i++) {
535 float x = ((float) i) * (1.0f / ((float) (outTableSize - 1)));
536 float y = inverse_parametric(x, g, a, b, c, d, e, f);
537 outTable[i] = clamp_normalized_float_to_byte(y);
538 }
539 }
540
541 SkDefaultXform::SkDefaultXform(const sk_sp<SkColorSpace>& srcSpace, const SkMatr ix44& srcToDst,
542 const sk_sp<SkColorSpace>& dstSpace)
543 : fSrcToDst(srcToDst)
544 {
545 // Build tables to transform src gamma to linear.
546 switch (srcSpace->gammaNamed()) {
547 case SkColorSpace::kSRGB_GammaNamed:
548 fSrcGammaTables[0] = fSrcGammaTables[1] = fSrcGammaTables[2] = sk_li near_from_srgb;
549 break;
550 case SkColorSpace::k2Dot2Curve_GammaNamed:
551 fSrcGammaTables[0] = fSrcGammaTables[1] = fSrcGammaTables[2] = sk_li near_from_2dot2;
552 break;
553 case SkColorSpace::kLinear_GammaNamed:
554 build_table_linear_from_gamma(fSrcGammaTableStorage, 1.0f);
555 fSrcGammaTables[0] = fSrcGammaTables[1] = fSrcGammaTables[2] = fSrcG ammaTableStorage;
556 break;
557 default: {
558 const SkGammas* gammas = as_CSB(srcSpace)->gammas();
559 SkASSERT(gammas);
560
561 for (int i = 0; i < 3; i++) {
562 const SkGammaCurve& curve = (*gammas)[i];
563
564 if (i > 0) {
565 // Check if this curve matches the first curve. In this cas e, we can
566 // share the same table pointer. Logically, this should alm ost always
567 // be true. I've never seen a profile where all three gamma curves
568 // didn't match. But it is possible that they won't.
569 // TODO (msarett):
570 // This comparison won't catch the case where each gamma cur ve has a
571 // pointer to its own look-up table, but the tables actually match.
572 // Should we perform a deep compare of gamma tables here? O r should
573 // we catch this when parsing the profile? Or should we not worry
574 // about a bit of redundant work?
575 if (curve.quickEquals((*gammas)[0])) {
576 fSrcGammaTables[i] = fSrcGammaTables[0];
577 continue;
578 }
579 }
580
581 if (curve.isNamed()) {
582 switch (curve.fNamed) {
583 case SkColorSpace::kSRGB_GammaNamed:
584 fSrcGammaTables[i] = sk_linear_from_srgb;
585 break;
586 case SkColorSpace::k2Dot2Curve_GammaNamed:
587 fSrcGammaTables[i] = sk_linear_from_2dot2;
588 break;
589 case SkColorSpace::kLinear_GammaNamed:
590 build_table_linear_from_gamma(&fSrcGammaTableStorage [i * 256], 1.0f);
591 fSrcGammaTables[i] = &fSrcGammaTableStorage[i * 256] ;
592 break;
593 default:
594 SkASSERT(false);
595 break;
596 }
597 } else if (curve.isValue()) {
598 build_table_linear_from_gamma(&fSrcGammaTableStorage[i * 256 ], curve.fValue);
599 fSrcGammaTables[i] = &fSrcGammaTableStorage[i * 256];
600 } else if (curve.isTable()) {
601 build_table_linear_from_gamma(&fSrcGammaTableStorage[i * 256 ],
602 curve.fTable.get(), curve.fTab leSize);
603 fSrcGammaTables[i] = &fSrcGammaTableStorage[i * 256];
604 } else {
605 SkASSERT(curve.isParametric());
606 build_table_linear_from_gamma(&fSrcGammaTableStorage[i * 256 ], curve.fG,
607 curve.fA, curve.fB, curve.fC, curve.fD, curve.fE,
608 curve.fF);
609 fSrcGammaTables[i] = &fSrcGammaTableStorage[i * 256];
610 }
611 }
612 }
613 }
614
615 // Build tables to transform linear to dst gamma.
616 switch (dstSpace->gammaNamed()) {
617 case SkColorSpace::kSRGB_GammaNamed:
618 fDstGammaTables[0] = fDstGammaTables[1] = fDstGammaTables[2] = linea r_to_srgb;
619 break;
620 case SkColorSpace::k2Dot2Curve_GammaNamed:
621 fDstGammaTables[0] = fDstGammaTables[1] = fDstGammaTables[2] = linea r_to_2dot2;
622 break;
623 case SkColorSpace::kLinear_GammaNamed:
624 build_table_linear_to_gamma(fDstGammaTableStorage, kDstGammaTableSiz e, 1.0f);
625 fDstGammaTables[0] = fDstGammaTables[1] = fDstGammaTables[2] = fDstG ammaTableStorage;
626 break;
627 default: {
628 const SkGammas* gammas = as_CSB(dstSpace)->gammas();
629 SkASSERT(gammas);
630
631 for (int i = 0; i < 3; i++) {
632 const SkGammaCurve& curve = (*gammas)[i];
633
634 if (i > 0) {
635 // Check if this curve matches the first curve. In this cas e, we can
636 // share the same table pointer. Logically, this should alm ost always
637 // be true. I've never seen a profile where all three gamma curves
638 // didn't match. But it is possible that they won't.
639 // TODO (msarett):
640 // This comparison won't catch the case where each gamma cur ve has a
641 // pointer to its own look-up table (but the tables actually match).
642 // Should we perform a deep compare of gamma tables here? O r should
643 // we catch this when parsing the profile? Or should we not worry
644 // about a bit of redundant work?
645 if (curve.quickEquals((*gammas)[0])) {
646 fDstGammaTables[i] = fDstGammaTables[0];
647 continue;
648 }
649 }
650
651 if (curve.isNamed()) {
652 switch (curve.fNamed) {
653 case SkColorSpace::kSRGB_GammaNamed:
654 fDstGammaTables[i] = linear_to_srgb;
655 break;
656 case SkColorSpace::k2Dot2Curve_GammaNamed:
657 fDstGammaTables[i] = linear_to_2dot2;
658 break;
659 case SkColorSpace::kLinear_GammaNamed:
660 build_table_linear_to_gamma(
661 &fDstGammaTableStorage[i * kDstGammaTableSiz e],
662 kDstGammaTableSize, 1.0f);
663 fDstGammaTables[i] = &fDstGammaTableStorage[i * kDst GammaTableSize];
664 break;
665 default:
666 SkASSERT(false);
667 break;
668 }
669 } else if (curve.isValue()) {
670 build_table_linear_to_gamma(&fDstGammaTableStorage[i * kDstG ammaTableSize],
671 kDstGammaTableSize, curve.fValue );
672 fDstGammaTables[i] = &fDstGammaTableStorage[i * kDstGammaTab leSize];
673 } else if (curve.isTable()) {
674 build_table_linear_to_gamma(&fDstGammaTableStorage[i * kDstG ammaTableSize],
675 kDstGammaTableSize, curve.fTable .get(),
676 curve.fTableSize);
677 fDstGammaTables[i] = &fDstGammaTableStorage[i * kDstGammaTab leSize];
678 } else {
679 SkASSERT(curve.isParametric());
680 build_table_linear_to_gamma(&fDstGammaTableStorage[i * kDstG ammaTableSize],
681 kDstGammaTableSize, curve.fG, cu rve.fA, curve.fB,
682 curve.fC, curve.fD, curve.fE, cu rve.fF);
683 fDstGammaTables[i] = &fDstGammaTableStorage[i * kDstGammaTab leSize];
684 }
685 }
686 }
687 }
688 }
689
690 // Clamp to the 0-1 range.
691 static float clamp_normalized_float(float v) {
692 if (v > 1.0f) {
693 return 1.0f;
694 } else if ((v < 0.0f) || (v != v)) {
695 return 0.0f;
696 } else {
697 return v;
698 }
699 }
212 700
213 void SkDefaultXform::xform_RGB1_8888(uint32_t* dst, const uint32_t* src, uint32_ t len) const { 701 void SkDefaultXform::xform_RGB1_8888(uint32_t* dst, const uint32_t* src, uint32_ t len) const {
214 while (len-- > 0) { 702 while (len-- > 0) {
215 // Convert to linear. 703 // Convert to linear.
216 // FIXME (msarett):
217 // Rather than support three different strategies of transforming gamma, QCMS
218 // builds a 256 entry float lookup table from the gamma info. This hand les
219 // the gamma transform and the conversion from bytes to floats. This ma y
220 // be simpler and faster than our current approach.
221 float srcFloats[3]; 704 float srcFloats[3];
222 for (int i = 0; i < 3; i++) { 705 srcFloats[0] = fSrcGammaTables[0][(*src >> 0) & 0xFF];
223 uint8_t byte = (*src >> (8 * i)) & 0xFF; 706 srcFloats[1] = fSrcGammaTables[1][(*src >> 8) & 0xFF];
224 if (fSrcGammas) { 707 srcFloats[2] = fSrcGammaTables[2][(*src >> 16) & 0xFF];
225 const SkGammaCurve& gamma = (*fSrcGammas)[i];
226 if (gamma.isValue()) {
227 srcFloats[i] = powf(byte_to_float(byte), gamma.fValue);
228 } else if (gamma.isTable()) {
229 srcFloats[i] = interp_lut(byte, gamma.fTable.get(), gamma.fT ableSize);
230 } else {
231 SkASSERT(gamma.isParametric());
232 float component = byte_to_float(byte);
233 if (component < gamma.fD) {
234 // Y = E * X + F
235 srcFloats[i] = gamma.fE * component + gamma.fF;
236 } else {
237 // Y = (A * X + B)^G + C
238 srcFloats[i] = powf(gamma.fA * component + gamma.fB, gam ma.fG) + gamma.fC;
239 }
240 }
241 } else {
242 // FIXME: Handle named gammas.
243 srcFloats[i] = powf(byte_to_float(byte), 2.2f);
244 }
245 }
246 708
247 // Convert to dst gamut. 709 // Convert to dst gamut.
248 float dstFloats[3]; 710 float dstFloats[3];
249 dstFloats[0] = srcFloats[0] * fSrcToDst.getFloat(0, 0) + 711 dstFloats[0] = srcFloats[0] * fSrcToDst.getFloat(0, 0) +
250 srcFloats[1] * fSrcToDst.getFloat(1, 0) + 712 srcFloats[1] * fSrcToDst.getFloat(1, 0) +
251 srcFloats[2] * fSrcToDst.getFloat(2, 0) + fSrcToDst.getFl oat(3, 0); 713 srcFloats[2] * fSrcToDst.getFloat(2, 0) + fSrcToDst.getFl oat(3, 0);
252 dstFloats[1] = srcFloats[0] * fSrcToDst.getFloat(0, 1) + 714 dstFloats[1] = srcFloats[0] * fSrcToDst.getFloat(0, 1) +
253 srcFloats[1] * fSrcToDst.getFloat(1, 1) + 715 srcFloats[1] * fSrcToDst.getFloat(1, 1) +
254 srcFloats[2] * fSrcToDst.getFloat(2, 1) + fSrcToDst.getFl oat(3, 1); 716 srcFloats[2] * fSrcToDst.getFloat(2, 1) + fSrcToDst.getFl oat(3, 1);
255 dstFloats[2] = srcFloats[0] * fSrcToDst.getFloat(0, 2) + 717 dstFloats[2] = srcFloats[0] * fSrcToDst.getFloat(0, 2) +
256 srcFloats[1] * fSrcToDst.getFloat(1, 2) + 718 srcFloats[1] * fSrcToDst.getFloat(1, 2) +
257 srcFloats[2] * fSrcToDst.getFloat(2, 2) + fSrcToDst.getFl oat(3, 2); 719 srcFloats[2] * fSrcToDst.getFloat(2, 2) + fSrcToDst.getFl oat(3, 2);
258 720
721 // Clamp to 0-1.
722 dstFloats[0] = clamp_normalized_float(dstFloats[0]);
723 dstFloats[1] = clamp_normalized_float(dstFloats[1]);
724 dstFloats[2] = clamp_normalized_float(dstFloats[2]);
725
259 // Convert to dst gamma. 726 // Convert to dst gamma.
260 // FIXME (msarett): 727 uint8_t r = fDstGammaTables[0][sk_float_round2int((kDstGammaTableSize - 1) * dstFloats[0])];
261 // Rather than support three different strategies of transforming invers e gamma, 728 uint8_t g = fDstGammaTables[1][sk_float_round2int((kDstGammaTableSize - 1) * dstFloats[1])];
262 // QCMS builds a large float lookup table from the gamma info. Is this faster or 729 uint8_t b = fDstGammaTables[2][sk_float_round2int((kDstGammaTableSize - 1) * dstFloats[2])];
263 // better than our approach?
264 for (int i = 0; i < 3; i++) {
265 if (fDstGammas) {
266 const SkGammaCurve& gamma = (*fDstGammas)[i];
267 if (gamma.isValue()) {
268 dstFloats[i] = powf(dstFloats[i], 1.0f / gamma.fValue);
269 } else if (gamma.isTable()) {
270 // FIXME (msarett):
271 // An inverse table lookup is particularly strange and non-o ptimal.
272 dstFloats[i] = interp_lut_inv(dstFloats[i], gamma.fTable.get (),
273 gamma.fTableSize);
274 } else {
275 SkASSERT(gamma.isParametric());
276 // FIXME (msarett):
277 // This is a placeholder implementation for inverting parame tric gammas.
278 // First, I need to verify if there are actually destination profiles that
279 // require this functionality. Next, I need to explore other possibilities
280 // for this implementation. The LUT based approach in QCMS would be a good
281 // place to start.
282 730
283 // We need to take the inverse of a piecewise function. Ass ume that 731 *dst = SkPackARGB32NoCheck(0xFF, r, g, b);
284 // the gamma function is continuous, or this won't make much sense
285 // anyway.
286 // Plug in |fD| to the first equation to calculate the new p iecewise
287 // interval. Then simply use the inverse of the original fu nctions.
288 float interval = gamma.fE * gamma.fD + gamma.fF;
289 if (dstFloats[i] < interval) {
290 // X = (Y - F) / E
291 if (0.0f == gamma.fE) {
292 // The gamma curve for this segment is constant, so the inverse
293 // is undefined.
294 dstFloats[i] = 0.0f;
295 } else {
296 dstFloats[i] = (dstFloats[i] - gamma.fF) / gamma.fE;
297 }
298 } else {
299 // X = ((Y - C)^(1 / G) - B) / A
300 if (0.0f == gamma.fA || 0.0f == gamma.fG) {
301 // The gamma curve for this segment is constant, so the inverse
302 // is undefined.
303 dstFloats[i] = 0.0f;
304 } else {
305 dstFloats[i] = (powf(dstFloats[i] - gamma.fC, 1.0f / gamma.fG) -
306 gamma.fB) / gamma.fA;
307 }
308 }
309 }
310 } else {
311 // FIXME: Handle named gammas.
312 dstFloats[i] = powf(dstFloats[i], 1.0f / 2.2f);
313 }
314 }
315
316 *dst = SkPackARGB32NoCheck(((*src >> 24) & 0xFF),
317 clamp_normalized_float_to_byte(dstFloats[0]),
318 clamp_normalized_float_to_byte(dstFloats[1]),
319 clamp_normalized_float_to_byte(dstFloats[2])) ;
320 732
321 dst++; 733 dst++;
322 src++; 734 src++;
323 } 735 }
324 } 736 }
OLDNEW
« no previous file with comments | « src/core/SkColorSpaceXform.h ('k') | src/core/SkColorSpace_Base.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698