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

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

Issue 2171623002: Revert of Refactor parsing and storage of SkGammas (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 4 years, 5 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 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 v = v * 255.0f; 257 v = v * 255.0f;
258 if (v >= 254.5f) { 258 if (v >= 254.5f) {
259 return 255; 259 return 255;
260 } else if (v >= 0.5f) { 260 } else if (v >= 0.5f) {
261 return (uint8_t) (v + 0.5f); 261 return (uint8_t) (v + 0.5f);
262 } else { 262 } else {
263 return 0; 263 return 0;
264 } 264 }
265 } 265 }
266 266
267 static void build_table_linear_to_gamma(uint8_t* outTable, float exponent) { 267 static void build_table_linear_to_gamma(uint8_t* outTable, int outTableSize, flo at exponent) {
268 float toGammaExp = 1.0f / exponent; 268 float toGammaExp = 1.0f / exponent;
269 269
270 for (int i = 0; i < SkDefaultXform::kDstGammaTableSize; i++) { 270 for (int i = 0; i < outTableSize; i++) {
271 float x = ((float) i) * (1.0f / ((float) (SkDefaultXform::kDstGammaTable Size - 1))); 271 float x = ((float) i) * (1.0f / ((float) (outTableSize - 1)));
272 outTable[i] = clamp_normalized_float_to_byte(powf(x, toGammaExp)); 272 outTable[i] = clamp_normalized_float_to_byte(powf(x, toGammaExp));
273 } 273 }
274 } 274 }
275 275
276 // Inverse table lookup. Ex: what index corresponds to the input value? This w ill 276 // Inverse table lookup. Ex: what index corresponds to the input value? This w ill
277 // have strange results when the table is non-increasing. But any sane gamma 277 // have strange results when the table is non-increasing. But any sane gamma
278 // function will be increasing. 278 // function will be increasing.
279 static float inverse_interp_lut(float input, const float* table, int tableSize) { 279 static float inverse_interp_lut(float input, float* table, int tableSize) {
280 if (input <= table[0]) { 280 if (input <= table[0]) {
281 return table[0]; 281 return table[0];
282 } else if (input >= table[tableSize - 1]) { 282 } else if (input >= table[tableSize - 1]) {
283 return 1.0f; 283 return 1.0f;
284 } 284 }
285 285
286 for (int i = 1; i < tableSize; i++) { 286 for (int i = 1; i < tableSize; i++) {
287 if (table[i] >= input) { 287 if (table[i] >= input) {
288 // We are guaranteed that input is greater than table[i - 1]. 288 // We are guaranteed that input is greater than table[i - 1].
289 float diff = input - table[i - 1]; 289 float diff = input - table[i - 1];
290 float distance = table[i] - table[i - 1]; 290 float distance = table[i] - table[i - 1];
291 float index = (i - 1) + diff / distance; 291 float index = (i - 1) + diff / distance;
292 return index / (tableSize - 1); 292 return index / (tableSize - 1);
293 } 293 }
294 } 294 }
295 295
296 // Should be unreachable, since we'll return before the loop if input is 296 // Should be unreachable, since we'll return before the loop if input is
297 // larger than the last entry. 297 // larger than the last entry.
298 SkASSERT(false); 298 SkASSERT(false);
299 return 0.0f; 299 return 0.0f;
300 } 300 }
301 301
302 static void build_table_linear_to_gamma(uint8_t* outTable, const float* inTable, 302 static void build_table_linear_to_gamma(uint8_t* outTable, int outTableSize, flo at* inTable,
303 int inTableSize) { 303 int inTableSize) {
304 for (int i = 0; i < SkDefaultXform::kDstGammaTableSize; i++) { 304 for (int i = 0; i < outTableSize; i++) {
305 float x = ((float) i) * (1.0f / ((float) (SkDefaultXform::kDstGammaTable Size - 1))); 305 float x = ((float) i) * (1.0f / ((float) (outTableSize - 1)));
306 float y = inverse_interp_lut(x, inTable, inTableSize); 306 float y = inverse_interp_lut(x, inTable, inTableSize);
307 outTable[i] = clamp_normalized_float_to_byte(y); 307 outTable[i] = clamp_normalized_float_to_byte(y);
308 } 308 }
309 } 309 }
310 310
311 static float inverse_parametric(float x, float g, float a, float b, float c, flo at d, float e, 311 static float inverse_parametric(float x, float g, float a, float b, float c, flo at d, float e,
312 float f) { 312 float f) {
313 // We need to take the inverse of the following piecewise function. 313 // We need to take the inverse of the following piecewise function.
314 // Y = (aX + b)^g + c for X >= d 314 // Y = (aX + b)^g + c for X >= d
315 // Y = eX + f otherwise 315 // Y = eX + f otherwise
(...skipping 16 matching lines...) Expand all
332 // X = ((Y - C)^(1 / G) - B) / A 332 // X = ((Y - C)^(1 / G) - B) / A
333 if (0.0f == a || 0.0f == g) { 333 if (0.0f == a || 0.0f == g) {
334 // The gamma curve for this segment is constant, so the inverse is undef ined. 334 // The gamma curve for this segment is constant, so the inverse is undef ined.
335 // Since this is the upper segment, guess one. 335 // Since this is the upper segment, guess one.
336 return 1.0f; 336 return 1.0f;
337 } 337 }
338 338
339 return (powf(x - c, 1.0f / g) - b) / a; 339 return (powf(x - c, 1.0f / g) - b) / a;
340 } 340 }
341 341
342 static void build_table_linear_to_gamma(uint8_t* outTable, float g, float a, 342 static void build_table_linear_to_gamma(uint8_t* outTable, int outTableSize, flo at g, float a,
343 float b, float c, float d, float e, floa t f) { 343 float b, float c, float d, float e, floa t f) {
344 for (int i = 0; i < SkDefaultXform::kDstGammaTableSize; i++) { 344 for (int i = 0; i < outTableSize; i++) {
345 float x = ((float) i) * (1.0f / ((float) (SkDefaultXform::kDstGammaTable Size - 1))); 345 float x = ((float) i) * (1.0f / ((float) (outTableSize - 1)));
346 float y = inverse_parametric(x, g, a, b, c, d, e, f); 346 float y = inverse_parametric(x, g, a, b, c, d, e, f);
347 outTable[i] = clamp_normalized_float_to_byte(y); 347 outTable[i] = clamp_normalized_float_to_byte(y);
348 } 348 }
349 } 349 }
350 350
351 //////////////////////////////////////////////////////////////////////////////// ///////////////////
352
353 template <typename T>
354 struct GammaFns {
355 const T* fSRGBTable;
356 const T* f2Dot2Table;
357
358 void (*fBuildFromValue)(T*, float);
359 void (*fBuildFromTable)(T*, const float*, int);
360 void (*fBuildFromParam)(T*, float, float, float, float, float, float, float) ;
361 };
362
363 static const GammaFns<float> kToLinear {
364 sk_linear_from_srgb,
365 sk_linear_from_2dot2,
366 &build_table_linear_from_gamma,
367 &build_table_linear_from_gamma,
368 &build_table_linear_from_gamma,
369 };
370
371 static const GammaFns<uint8_t> kFromLinear {
372 linear_to_srgb,
373 linear_to_2dot2,
374 &build_table_linear_to_gamma,
375 &build_table_linear_to_gamma,
376 &build_table_linear_to_gamma,
377 };
378
379 // Build tables to transform src gamma to linear.
380 template <typename T>
381 static void build_gamma_tables(const T* outGammaTables[3], T* gammaTableStorage, int gammaTableSize,
382 const sk_sp<SkColorSpace>& space, const GammaFns< T>& fns) {
383 switch (space->gammaNamed()) {
384 case SkColorSpace::kSRGB_GammaNamed:
385 outGammaTables[0] = outGammaTables[1] = outGammaTables[2] = fns.fSRG BTable;
386 break;
387 case SkColorSpace::k2Dot2Curve_GammaNamed:
388 outGammaTables[0] = outGammaTables[1] = outGammaTables[2] = fns.f2Do t2Table;
389 break;
390 case SkColorSpace::kLinear_GammaNamed:
391 (*fns.fBuildFromValue)(gammaTableStorage, 1.0f);
392 outGammaTables[0] = outGammaTables[1] = outGammaTables[2] = gammaTab leStorage;
393 break;
394 default: {
395 const SkGammas* gammas = as_CSB(space)->gammas();
396 SkASSERT(gammas);
397
398 for (int i = 0; i < 3; i++) {
399 if (i > 0) {
400 // Check if this curve matches the first curve. In this cas e, we can
401 // share the same table pointer. This should almost always be true.
402 // I've never seen a profile where all three gamma curves di dn't match.
403 // But it is possible that they won't.
404 if (gammas->data(0) == gammas->data(i)) {
405 outGammaTables[i] = outGammaTables[0];
406 continue;
407 }
408 }
409
410 if (gammas->isNamed(i)) {
411 switch (gammas->data(i).fNamed) {
412 case SkColorSpace::kSRGB_GammaNamed:
413 outGammaTables[i] = fns.fSRGBTable;
414 break;
415 case SkColorSpace::k2Dot2Curve_GammaNamed:
416 outGammaTables[i] = fns.f2Dot2Table;
417 break;
418 case SkColorSpace::kLinear_GammaNamed:
419 (*fns.fBuildFromValue)(&gammaTableStorage[i * gammaT ableSize], 1.0f);
420 outGammaTables[i] = &gammaTableStorage[i * gammaTabl eSize];
421 break;
422 default:
423 SkASSERT(false);
424 break;
425 }
426 } else if (gammas->isValue(i)) {
427 (*fns.fBuildFromValue)(&gammaTableStorage[i * gammaTableSize ],
428 gammas->data(i).fValue);
429 outGammaTables[i] = &gammaTableStorage[i * gammaTableSize];
430 } else if (gammas->isTable(i)) {
431 (*fns.fBuildFromTable)(&gammaTableStorage[i * gammaTableSize ], gammas->table(i),
432 gammas->data(i).fTable.fSize);
433 outGammaTables[i] = &gammaTableStorage[i * gammaTableSize];
434 } else {
435 SkASSERT(gammas->isParametric(i));
436 const SkGammas::Params& params = gammas->params(i);
437 (*fns.fBuildFromParam)(&gammaTableStorage[i * gammaTableSize ], params.fG,
438 params.fA, params.fB, params.fC, para ms.fD, params.fE,
439 params.fF);
440 outGammaTables[i] = &gammaTableStorage[i * gammaTableSize];
441 }
442 }
443 }
444 }
445 }
446
447 //////////////////////////////////////////////////////////////////////////////// /////////////////// 351 //////////////////////////////////////////////////////////////////////////////// ///////////////////
448 352
449 std::unique_ptr<SkColorSpaceXform> SkColorSpaceXform::New(const sk_sp<SkColorSpa ce>& srcSpace, 353 std::unique_ptr<SkColorSpaceXform> SkColorSpaceXform::New(const sk_sp<SkColorSpa ce>& srcSpace,
450 const sk_sp<SkColorSpa ce>& dstSpace) { 354 const sk_sp<SkColorSpa ce>& dstSpace) {
451 if (!srcSpace || !dstSpace) { 355 if (!srcSpace || !dstSpace) {
452 // Invalid input 356 // Invalid input
453 return nullptr; 357 return nullptr;
454 } 358 }
455 359
456 if (as_CSB(dstSpace)->colorLUT()) { 360 if (as_CSB(dstSpace)->colorLUT()) {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
509 srcToDstArray[9] = srcToDstMatrix.getFloat(2, 1); 413 srcToDstArray[9] = srcToDstMatrix.getFloat(2, 1);
510 srcToDstArray[10] = srcToDstMatrix.getFloat(2, 2); 414 srcToDstArray[10] = srcToDstMatrix.getFloat(2, 2);
511 srcToDstArray[11] = 0.0f; 415 srcToDstArray[11] = 0.0f;
512 } 416 }
513 417
514 template <SkColorSpace::GammaNamed Dst> 418 template <SkColorSpace::GammaNamed Dst>
515 SkFastXform<Dst>::SkFastXform(const sk_sp<SkColorSpace>& srcSpace, const SkMatri x44& srcToDst, 419 SkFastXform<Dst>::SkFastXform(const sk_sp<SkColorSpace>& srcSpace, const SkMatri x44& srcToDst,
516 const sk_sp<SkColorSpace>& dstSpace) 420 const sk_sp<SkColorSpace>& dstSpace)
517 { 421 {
518 build_src_to_dst(fSrcToDst, srcToDst); 422 build_src_to_dst(fSrcToDst, srcToDst);
519 build_gamma_tables(fSrcGammaTables, fSrcGammaTableStorage, 256, srcSpace, kT oLinear); 423
520 build_gamma_tables(fDstGammaTables, fDstGammaTableStorage, SkDefaultXform::k DstGammaTableSize, 424 // Build tables to transform src gamma to linear.
521 dstSpace, kFromLinear); 425 switch (srcSpace->gammaNamed()) {
426 case SkColorSpace::kSRGB_GammaNamed:
427 fSrcGammaTables[0] = fSrcGammaTables[1] = fSrcGammaTables[2] = sk_li near_from_srgb;
428 break;
429 case SkColorSpace::k2Dot2Curve_GammaNamed:
430 fSrcGammaTables[0] = fSrcGammaTables[1] = fSrcGammaTables[2] = sk_li near_from_2dot2;
431 break;
432 case SkColorSpace::kLinear_GammaNamed:
433 build_table_linear_from_gamma(fSrcGammaTableStorage, 1.0f);
434 fSrcGammaTables[0] = fSrcGammaTables[1] = fSrcGammaTables[2] = fSrcG ammaTableStorage;
435 break;
436 default: {
437 const SkGammas* gammas = as_CSB(srcSpace)->gammas();
438 SkASSERT(gammas);
439
440 for (int i = 0; i < 3; i++) {
441 const SkGammaCurve& curve = (*gammas)[i];
442
443 if (i > 0) {
444 // Check if this curve matches the first curve. In this cas e, we can
445 // share the same table pointer. Logically, this should alm ost always
446 // be true. I've never seen a profile where all three gamma curves
447 // didn't match. But it is possible that they won't.
448 // TODO (msarett):
449 // This comparison won't catch the case where each gamma cur ve has a
450 // pointer to its own look-up table, but the tables actually match.
451 // Should we perform a deep compare of gamma tables here? O r should
452 // we catch this when parsing the profile? Or should we not worry
453 // about a bit of redundant work?
454 if (curve.quickEquals((*gammas)[0])) {
455 fSrcGammaTables[i] = fSrcGammaTables[0];
456 continue;
457 }
458 }
459
460 if (curve.isNamed()) {
461 switch (curve.fNamed) {
462 case SkColorSpace::kSRGB_GammaNamed:
463 fSrcGammaTables[i] = sk_linear_from_srgb;
464 break;
465 case SkColorSpace::k2Dot2Curve_GammaNamed:
466 fSrcGammaTables[i] = sk_linear_from_2dot2;
467 break;
468 case SkColorSpace::kLinear_GammaNamed:
469 build_table_linear_from_gamma(&fSrcGammaTableStorage [i * 256], 1.0f);
470 fSrcGammaTables[i] = &fSrcGammaTableStorage[i * 256] ;
471 break;
472 default:
473 SkASSERT(false);
474 break;
475 }
476 } else if (curve.isValue()) {
477 build_table_linear_from_gamma(&fSrcGammaTableStorage[i * 256 ], curve.fValue);
478 fSrcGammaTables[i] = &fSrcGammaTableStorage[i * 256];
479 } else if (curve.isTable()) {
480 build_table_linear_from_gamma(&fSrcGammaTableStorage[i * 256 ],
481 curve.fTable.get(), curve.fTab leSize);
482 fSrcGammaTables[i] = &fSrcGammaTableStorage[i * 256];
483 } else {
484 SkASSERT(curve.isParametric());
485 build_table_linear_from_gamma(&fSrcGammaTableStorage[i * 256 ], curve.fG,
486 curve.fA, curve.fB, curve.fC, curve.fD, curve.fE,
487 curve.fF);
488 fSrcGammaTables[i] = &fSrcGammaTableStorage[i * 256];
489 }
490 }
491 }
492 }
493
494 // Build tables to transform linear to dst gamma.
495 // FIXME (msarett):
496 // Should we spend all of this time bulding the dst gamma tables when the cl ient only
497 // wants to convert to F16?
498 switch (dstSpace->gammaNamed()) {
499 case SkColorSpace::kSRGB_GammaNamed:
500 case SkColorSpace::k2Dot2Curve_GammaNamed:
501 break;
502 case SkColorSpace::kLinear_GammaNamed:
503 build_table_linear_to_gamma(fDstGammaTableStorage, kDstGammaTableSiz e, 1.0f);
504 fDstGammaTables[0] = fDstGammaTables[1] = fDstGammaTables[2] = fDstG ammaTableStorage;
505 break;
506 default: {
507 const SkGammas* gammas = as_CSB(dstSpace)->gammas();
508 SkASSERT(gammas);
509
510 for (int i = 0; i < 3; i++) {
511 const SkGammaCurve& curve = (*gammas)[i];
512
513 if (i > 0) {
514 // Check if this curve matches the first curve. In this cas e, we can
515 // share the same table pointer. Logically, this should alm ost always
516 // be true. I've never seen a profile where all three gamma curves
517 // didn't match. But it is possible that they won't.
518 // TODO (msarett):
519 // This comparison won't catch the case where each gamma cur ve has a
520 // pointer to its own look-up table (but the tables actually match).
521 // Should we perform a deep compare of gamma tables here? O r should
522 // we catch this when parsing the profile? Or should we not worry
523 // about a bit of redundant work?
524 if (curve.quickEquals((*gammas)[0])) {
525 fDstGammaTables[i] = fDstGammaTables[0];
526 continue;
527 }
528 }
529
530 if (curve.isNamed()) {
531 switch (curve.fNamed) {
532 case SkColorSpace::kSRGB_GammaNamed:
533 fDstGammaTables[i] = linear_to_srgb;
534 break;
535 case SkColorSpace::k2Dot2Curve_GammaNamed:
536 fDstGammaTables[i] = linear_to_2dot2;
537 break;
538 case SkColorSpace::kLinear_GammaNamed:
539 build_table_linear_to_gamma(
540 &fDstGammaTableStorage[i * kDstGammaTableSiz e],
541 kDstGammaTableSize, 1.0f);
542 fDstGammaTables[i] = &fDstGammaTableStorage[i * kDst GammaTableSize];
543 break;
544 default:
545 SkASSERT(false);
546 break;
547 }
548 } else if (curve.isValue()) {
549 build_table_linear_to_gamma(&fDstGammaTableStorage[i * kDstG ammaTableSize],
550 kDstGammaTableSize, curve.fValue );
551 fDstGammaTables[i] = &fDstGammaTableStorage[i * kDstGammaTab leSize];
552 } else if (curve.isTable()) {
553 build_table_linear_to_gamma(&fDstGammaTableStorage[i * kDstG ammaTableSize],
554 kDstGammaTableSize, curve.fTable .get(),
555 curve.fTableSize);
556 fDstGammaTables[i] = &fDstGammaTableStorage[i * kDstGammaTab leSize];
557 } else {
558 SkASSERT(curve.isParametric());
559 build_table_linear_to_gamma(&fDstGammaTableStorage[i * kDstG ammaTableSize],
560 kDstGammaTableSize, curve.fG, cu rve.fA, curve.fB,
561 curve.fC, curve.fD, curve.fE, cu rve.fF);
562 fDstGammaTables[i] = &fDstGammaTableStorage[i * kDstGammaTab leSize];
563 }
564 }
565 }
566 }
522 } 567 }
523 568
524 template <> 569 template <>
525 void SkFastXform<SkColorSpace::kSRGB_GammaNamed> 570 void SkFastXform<SkColorSpace::kSRGB_GammaNamed>
526 ::applyTo8888(SkPMColor* dst, const RGBA32* src, int len) const 571 ::applyTo8888(SkPMColor* dst, const RGBA32* src, int len) const
527 { 572 {
528 SkOpts::color_xform_RGB1_to_srgb(dst, src, len, fSrcGammaTables, fSrcToDst); 573 SkOpts::color_xform_RGB1_to_srgb(dst, src, len, fSrcGammaTables, fSrcToDst);
529 } 574 }
530 575
531 template <> 576 template <>
(...skipping 17 matching lines...) Expand all
549 SkOpts::color_xform_RGB1_to_linear(dst, src, len, fSrcGammaTables, fSrcToDst ); 594 SkOpts::color_xform_RGB1_to_linear(dst, src, len, fSrcGammaTables, fSrcToDst );
550 } 595 }
551 596
552 //////////////////////////////////////////////////////////////////////////////// /////////////////// 597 //////////////////////////////////////////////////////////////////////////////// ///////////////////
553 598
554 SkDefaultXform::SkDefaultXform(const sk_sp<SkColorSpace>& srcSpace, const SkMatr ix44& srcToDst, 599 SkDefaultXform::SkDefaultXform(const sk_sp<SkColorSpace>& srcSpace, const SkMatr ix44& srcToDst,
555 const sk_sp<SkColorSpace>& dstSpace) 600 const sk_sp<SkColorSpace>& dstSpace)
556 : fColorLUT(sk_ref_sp((SkColorLookUpTable*) as_CSB(srcSpace)->colorLUT())) 601 : fColorLUT(sk_ref_sp((SkColorLookUpTable*) as_CSB(srcSpace)->colorLUT()))
557 , fSrcToDst(srcToDst) 602 , fSrcToDst(srcToDst)
558 { 603 {
559 build_gamma_tables(fSrcGammaTables, fSrcGammaTableStorage, 256, srcSpace, kT oLinear); 604 // Build tables to transform src gamma to linear.
560 build_gamma_tables(fDstGammaTables, fDstGammaTableStorage, SkDefaultXform::k DstGammaTableSize, 605 switch (srcSpace->gammaNamed()) {
561 dstSpace, kFromLinear); 606 case SkColorSpace::kSRGB_GammaNamed:
607 fSrcGammaTables[0] = fSrcGammaTables[1] = fSrcGammaTables[2] = sk_li near_from_srgb;
608 break;
609 case SkColorSpace::k2Dot2Curve_GammaNamed:
610 fSrcGammaTables[0] = fSrcGammaTables[1] = fSrcGammaTables[2] = sk_li near_from_2dot2;
611 break;
612 case SkColorSpace::kLinear_GammaNamed:
613 build_table_linear_from_gamma(fSrcGammaTableStorage, 1.0f);
614 fSrcGammaTables[0] = fSrcGammaTables[1] = fSrcGammaTables[2] = fSrcG ammaTableStorage;
615 break;
616 default: {
617 const SkGammas* gammas = as_CSB(srcSpace)->gammas();
618 SkASSERT(gammas);
619
620 for (int i = 0; i < 3; i++) {
621 const SkGammaCurve& curve = (*gammas)[i];
622
623 if (i > 0) {
624 // Check if this curve matches the first curve. In this cas e, we can
625 // share the same table pointer. Logically, this should alm ost always
626 // be true. I've never seen a profile where all three gamma curves
627 // didn't match. But it is possible that they won't.
628 // TODO (msarett):
629 // This comparison won't catch the case where each gamma cur ve has a
630 // pointer to its own look-up table, but the tables actually match.
631 // Should we perform a deep compare of gamma tables here? O r should
632 // we catch this when parsing the profile? Or should we not worry
633 // about a bit of redundant work?
634 if (curve.quickEquals((*gammas)[0])) {
635 fSrcGammaTables[i] = fSrcGammaTables[0];
636 continue;
637 }
638 }
639
640 if (curve.isNamed()) {
641 switch (curve.fNamed) {
642 case SkColorSpace::kSRGB_GammaNamed:
643 fSrcGammaTables[i] = sk_linear_from_srgb;
644 break;
645 case SkColorSpace::k2Dot2Curve_GammaNamed:
646 fSrcGammaTables[i] = sk_linear_from_2dot2;
647 break;
648 case SkColorSpace::kLinear_GammaNamed:
649 build_table_linear_from_gamma(&fSrcGammaTableStorage [i * 256], 1.0f);
650 fSrcGammaTables[i] = &fSrcGammaTableStorage[i * 256] ;
651 break;
652 default:
653 SkASSERT(false);
654 break;
655 }
656 } else if (curve.isValue()) {
657 build_table_linear_from_gamma(&fSrcGammaTableStorage[i * 256 ], curve.fValue);
658 fSrcGammaTables[i] = &fSrcGammaTableStorage[i * 256];
659 } else if (curve.isTable()) {
660 build_table_linear_from_gamma(&fSrcGammaTableStorage[i * 256 ],
661 curve.fTable.get(), curve.fTab leSize);
662 fSrcGammaTables[i] = &fSrcGammaTableStorage[i * 256];
663 } else {
664 SkASSERT(curve.isParametric());
665 build_table_linear_from_gamma(&fSrcGammaTableStorage[i * 256 ], curve.fG,
666 curve.fA, curve.fB, curve.fC, curve.fD, curve.fE,
667 curve.fF);
668 fSrcGammaTables[i] = &fSrcGammaTableStorage[i * 256];
669 }
670 }
671 }
672 }
673
674 // Build tables to transform linear to dst gamma.
675 switch (dstSpace->gammaNamed()) {
676 case SkColorSpace::kSRGB_GammaNamed:
677 fDstGammaTables[0] = fDstGammaTables[1] = fDstGammaTables[2] = linea r_to_srgb;
678 break;
679 case SkColorSpace::k2Dot2Curve_GammaNamed:
680 fDstGammaTables[0] = fDstGammaTables[1] = fDstGammaTables[2] = linea r_to_2dot2;
681 break;
682 case SkColorSpace::kLinear_GammaNamed:
683 build_table_linear_to_gamma(fDstGammaTableStorage, kDstGammaTableSiz e, 1.0f);
684 fDstGammaTables[0] = fDstGammaTables[1] = fDstGammaTables[2] = fDstG ammaTableStorage;
685 break;
686 default: {
687 const SkGammas* gammas = as_CSB(dstSpace)->gammas();
688 SkASSERT(gammas);
689
690 for (int i = 0; i < 3; i++) {
691 const SkGammaCurve& curve = (*gammas)[i];
692
693 if (i > 0) {
694 // Check if this curve matches the first curve. In this cas e, we can
695 // share the same table pointer. Logically, this should alm ost always
696 // be true. I've never seen a profile where all three gamma curves
697 // didn't match. But it is possible that they won't.
698 // TODO (msarett):
699 // This comparison won't catch the case where each gamma cur ve has a
700 // pointer to its own look-up table (but the tables actually match).
701 // Should we perform a deep compare of gamma tables here? O r should
702 // we catch this when parsing the profile? Or should we not worry
703 // about a bit of redundant work?
704 if (curve.quickEquals((*gammas)[0])) {
705 fDstGammaTables[i] = fDstGammaTables[0];
706 continue;
707 }
708 }
709
710 if (curve.isNamed()) {
711 switch (curve.fNamed) {
712 case SkColorSpace::kSRGB_GammaNamed:
713 fDstGammaTables[i] = linear_to_srgb;
714 break;
715 case SkColorSpace::k2Dot2Curve_GammaNamed:
716 fDstGammaTables[i] = linear_to_2dot2;
717 break;
718 case SkColorSpace::kLinear_GammaNamed:
719 build_table_linear_to_gamma(
720 &fDstGammaTableStorage[i * kDstGammaTableSiz e],
721 kDstGammaTableSize, 1.0f);
722 fDstGammaTables[i] = &fDstGammaTableStorage[i * kDst GammaTableSize];
723 break;
724 default:
725 SkASSERT(false);
726 break;
727 }
728 } else if (curve.isValue()) {
729 build_table_linear_to_gamma(&fDstGammaTableStorage[i * kDstG ammaTableSize],
730 kDstGammaTableSize, curve.fValue );
731 fDstGammaTables[i] = &fDstGammaTableStorage[i * kDstGammaTab leSize];
732 } else if (curve.isTable()) {
733 build_table_linear_to_gamma(&fDstGammaTableStorage[i * kDstG ammaTableSize],
734 kDstGammaTableSize, curve.fTable .get(),
735 curve.fTableSize);
736 fDstGammaTables[i] = &fDstGammaTableStorage[i * kDstGammaTab leSize];
737 } else {
738 SkASSERT(curve.isParametric());
739 build_table_linear_to_gamma(&fDstGammaTableStorage[i * kDstG ammaTableSize],
740 kDstGammaTableSize, curve.fG, cu rve.fA, curve.fB,
741 curve.fC, curve.fD, curve.fE, cu rve.fF);
742 fDstGammaTables[i] = &fDstGammaTableStorage[i * kDstGammaTab leSize];
743 }
744 }
745 }
746 }
562 } 747 }
563 748
564 static float byte_to_float(uint8_t byte) { 749 static float byte_to_float(uint8_t byte) {
565 return ((float) byte) * (1.0f / 255.0f); 750 return ((float) byte) * (1.0f / 255.0f);
566 } 751 }
567 752
568 // Clamp to the 0-1 range. 753 // Clamp to the 0-1 range.
569 static float clamp_normalized_float(float v) { 754 static float clamp_normalized_float(float v) {
570 if (v > 1.0f) { 755 if (v > 1.0f) {
571 return 1.0f; 756 return 1.0f;
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
722 dst++; 907 dst++;
723 src++; 908 src++;
724 } 909 }
725 } 910 }
726 911
727 void SkDefaultXform::applyToF16(RGBAF16* dst, const RGBA32* src, int len) const { 912 void SkDefaultXform::applyToF16(RGBAF16* dst, const RGBA32* src, int len) const {
728 // FIXME (msarett): 913 // FIXME (msarett):
729 // Planning to delete SkDefaultXform. Not going to bother to implement this . 914 // Planning to delete SkDefaultXform. Not going to bother to implement this .
730 memset(dst, 0, len * sizeof(RGBAF16)); 915 memset(dst, 0, len * sizeof(RGBAF16));
731 } 916 }
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