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

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

Issue 2389983002: Refactored SkColorSpace and added in a Lab PCS GM (Closed)
Patch Set: migrated call from SkColorSpace_Base::makeLinearGamma() to SkColorSpace_XYZ::makeLinearGamma() Created 4 years, 2 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/SkColorSpace.cpp ('k') | src/core/SkColorSpaceXform_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_A2B.h"
9 #include "SkColorSpace_Base.h" 10 #include "SkColorSpace_Base.h"
11 #include "SkColorSpace_XYZ.h"
10 #include "SkColorSpacePriv.h" 12 #include "SkColorSpacePriv.h"
11 #include "SkColorSpaceXform_Base.h" 13 #include "SkColorSpaceXform_Base.h"
12 #include "SkHalf.h" 14 #include "SkHalf.h"
13 #include "SkOpts.h" 15 #include "SkOpts.h"
14 #include "SkSRGB.h" 16 #include "SkSRGB.h"
15 17
16 static constexpr float sk_linear_from_2dot2[256] = { 18 static constexpr float sk_linear_from_2dot2[256] = {
17 0.000000000000000000f, 0.000005077051900662f, 0.000023328004666099f, 0.0 00056921765712193f, 19 0.000000000000000000f, 0.000005077051900662f, 0.000023328004666099f, 0.0 00056921765712193f,
18 0.000107187362341244f, 0.000175123977503027f, 0.000261543754548491f, 0.0 00367136269815943f, 20 0.000107187362341244f, 0.000175123977503027f, 0.000261543754548491f, 0.0 00367136269815943f,
19 0.000492503787191433f, 0.000638182842167022f, 0.000804658499513058f, 0.0 00992374304074325f, 21 0.000492503787191433f, 0.000638182842167022f, 0.000804658499513058f, 0.0 00992374304074325f,
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
247 nullptr, 249 nullptr,
248 nullptr, 250 nullptr,
249 &build_table_linear_to_gamma, 251 &build_table_linear_to_gamma,
250 &build_table_linear_to_gamma, 252 &build_table_linear_to_gamma,
251 &build_table_linear_to_gamma, 253 &build_table_linear_to_gamma,
252 }; 254 };
253 255
254 // Build tables to transform src gamma to linear. 256 // Build tables to transform src gamma to linear.
255 template <typename T> 257 template <typename T>
256 static void build_gamma_tables(const T* outGammaTables[3], T* gammaTableStorage, int gammaTableSize, 258 static void build_gamma_tables(const T* outGammaTables[3], T* gammaTableStorage, int gammaTableSize,
257 const SkColorSpace* space, const GammaFns<T>& fns , 259 const SkColorSpace_XYZ* space, const GammaFns<T>& fns,
258 bool gammasAreMatching) 260 bool gammasAreMatching)
259 { 261 {
260 switch (as_CSB(space)->gammaNamed()) { 262 switch (space->gammaNamed()) {
261 case kSRGB_SkGammaNamed: 263 case kSRGB_SkGammaNamed:
262 outGammaTables[0] = outGammaTables[1] = outGammaTables[2] = fns.fSRG BTable; 264 outGammaTables[0] = outGammaTables[1] = outGammaTables[2] = fns.fSRG BTable;
263 break; 265 break;
264 case k2Dot2Curve_SkGammaNamed: 266 case k2Dot2Curve_SkGammaNamed:
265 outGammaTables[0] = outGammaTables[1] = outGammaTables[2] = fns.f2Do t2Table; 267 outGammaTables[0] = outGammaTables[1] = outGammaTables[2] = fns.f2Do t2Table;
266 break; 268 break;
267 case kLinear_SkGammaNamed: 269 case kLinear_SkGammaNamed:
268 outGammaTables[0] = outGammaTables[1] = outGammaTables[2] = nullptr; 270 outGammaTables[0] = outGammaTables[1] = outGammaTables[2] = nullptr;
269 break; 271 break;
270 default: { 272 default: {
271 const SkGammas* gammas = as_CSB(space)->gammas(); 273 const SkGammas* gammas = space->gammas();
272 SkASSERT(gammas); 274 SkASSERT(gammas);
273 275
274 auto build_table = [=](int i) { 276 auto build_table = [=](int i) {
275 if (gammas->isNamed(i)) { 277 if (gammas->isNamed(i)) {
276 switch (gammas->data(i).fNamed) { 278 switch (gammas->data(i).fNamed) {
277 case kSRGB_SkGammaNamed: 279 case kSRGB_SkGammaNamed:
278 (*fns.fBuildFromParam)(&gammaTableStorage[i * gammaT ableSize], 2.4f, 280 (*fns.fBuildFromParam)(&gammaTableStorage[i * gammaT ableSize], 2.4f,
279 (1.0f / 1.055f), (0.055f / 1. 055f), 0.0f, 281 (1.0f / 1.055f), (0.055f / 1. 055f), 0.0f,
280 0.04045f, (1.0f / 12.92f), 0. 0f); 282 0.04045f, (1.0f / 12.92f), 0. 0f);
281 outGammaTables[i] = &gammaTableStorage[i * gammaTabl eSize]; 283 outGammaTables[i] = &gammaTableStorage[i * gammaTabl eSize];
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
319 build_table(1); 321 build_table(1);
320 build_table(2); 322 build_table(2);
321 } 323 }
322 324
323 break; 325 break;
324 } 326 }
325 } 327 }
326 } 328 }
327 329
328 void SkColorSpaceXform_Base::BuildDstGammaTables(const uint8_t* dstGammaTables[3 ], 330 void SkColorSpaceXform_Base::BuildDstGammaTables(const uint8_t* dstGammaTables[3 ],
329 uint8_t* dstStorage, const SkCo lorSpace* space, 331 uint8_t* dstStorage,
332 const SkColorSpace_XYZ* space,
330 bool gammasAreMatching) { 333 bool gammasAreMatching) {
331 build_gamma_tables(dstGammaTables, dstStorage, kDstGammaTableSize, space, kF romLinear, 334 build_gamma_tables(dstGammaTables, dstStorage, kDstGammaTableSize, space, kF romLinear,
332 gammasAreMatching); 335 gammasAreMatching);
333 } 336 }
334 337
335 //////////////////////////////////////////////////////////////////////////////// /////////////////// 338 //////////////////////////////////////////////////////////////////////////////// ///////////////////
336 339
337 static inline bool is_almost_identity(const SkMatrix44& srcToDst) { 340 static inline bool is_almost_identity(const SkMatrix44& srcToDst) {
338 for (int i = 0; i < 4; i++) { 341 for (int i = 0; i < 4; i++) {
339 for (int j = 0; j < 4; j++) { 342 for (int j = 0; j < 4; j++) {
340 float expected = (i == j) ? 1.0f : 0.0f; 343 float expected = (i == j) ? 1.0f : 0.0f;
341 if (!color_space_almost_equal(srcToDst.getFloat(i,j), expected)) { 344 if (!color_space_almost_equal(srcToDst.getFloat(i,j), expected)) {
342 return false; 345 return false;
343 } 346 }
344 } 347 }
345 } 348 }
346 return true; 349 return true;
347 } 350 }
348 351
349 //////////////////////////////////////////////////////////////////////////////// /////////////////// 352 //////////////////////////////////////////////////////////////////////////////// ///////////////////
350 353
351 std::unique_ptr<SkColorSpaceXform> SkColorSpaceXform::New(SkColorSpace* srcSpace , 354 std::unique_ptr<SkColorSpaceXform> SkColorSpaceXform::New(SkColorSpace* srcSpace ,
352 SkColorSpace* dstSpace ) { 355 SkColorSpace* dstSpace ) {
353 if (!srcSpace || !dstSpace) { 356 if (!srcSpace || !dstSpace) {
354 // Invalid input 357 // Invalid input
355 return nullptr; 358 return nullptr;
356 } 359 }
357 360
361 if (SkColorSpace_Base::Type::kA2B == as_CSB(dstSpace)->type()) {
362 SkColorSpacePrintf("A2B destinations not supported\n");
363 return nullptr;
364 }
365
366 if (SkColorSpace_Base::Type::kA2B == as_CSB(srcSpace)->type()) {
367 // TODO (raftias): return an A2B-supporting SkColorSpaceXform here once the xform.
368 // is implemented. SkColorSpaceXform_Base only supports XYZ+TRC based Sk ColorSpaces
369 //SkColorSpace_A2B* src = static_cast<SkColorSpace_A2B*>(srcSpace);
370 //SkColorSpace_XYZ* dst = static_cast<SkColorSpace_XYZ*>(dstSpace);
371 //return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_A2B(sr c, dst));
372 SkColorSpacePrintf("A2B sources not supported (yet)\n");
373 return nullptr;
374 }
375 SkColorSpace_XYZ* srcSpaceXYZ = static_cast<SkColorSpace_XYZ*>(srcSpace);
376 SkColorSpace_XYZ* dstSpaceXYZ = static_cast<SkColorSpace_XYZ*>(dstSpace);
377
358 ColorSpaceMatch csm = kNone_ColorSpaceMatch; 378 ColorSpaceMatch csm = kNone_ColorSpaceMatch;
359 SkMatrix44 srcToDst(SkMatrix44::kUninitialized_Constructor); 379 SkMatrix44 srcToDst(SkMatrix44::kUninitialized_Constructor);
360 if (SkColorSpace::Equals(srcSpace, dstSpace)) { 380 if (SkColorSpace::Equals(srcSpace, dstSpace)) {
361 srcToDst.setIdentity(); 381 srcToDst.setIdentity();
362 csm = kFull_ColorSpaceMatch; 382 csm = kFull_ColorSpaceMatch;
363 } else { 383 } else {
364 srcToDst.setConcat(as_CSB(dstSpace)->fromXYZD50(), as_CSB(srcSpace)->toX YZD50()); 384 srcToDst.setConcat(*dstSpaceXYZ->fromXYZD50(), *srcSpaceXYZ->toXYZD50()) ;
365 385
366 if (is_almost_identity(srcToDst)) { 386 if (is_almost_identity(srcToDst)) {
367 srcToDst.setIdentity(); 387 srcToDst.setIdentity();
368 csm = kGamut_ColorSpaceMatch; 388 csm = kGamut_ColorSpaceMatch;
369 } 389 }
370 } 390 }
371 391
372 switch (csm) { 392 switch (csm) {
373 case kNone_ColorSpaceMatch: 393 case kNone_ColorSpaceMatch:
374 switch (as_CSB(dstSpace)->gammaNamed()) { 394 switch (dstSpaceXYZ->gammaNamed()) {
375 case kSRGB_SkGammaNamed: 395 case kSRGB_SkGammaNamed:
376 if (srcSpace->gammaIsLinear()) { 396 if (srcSpaceXYZ->gammaIsLinear()) {
377 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpa ceXform_XYZ 397 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpa ceXform_XYZ
378 <kLinear_SrcGamma, kSRGB_DstGamma, kNone_ColorSp aceMatch> 398 <kLinear_SrcGamma, kSRGB_DstGamma, kNone_ColorSp aceMatch>
379 (srcSpace, srcToDst, dstSpace)); 399 (srcSpaceXYZ, srcToDst, dstSpaceXYZ));
380 } else { 400 } else {
381 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpa ceXform_XYZ 401 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpa ceXform_XYZ
382 <kTable_SrcGamma, kSRGB_DstGamma, kNone_ColorSpa ceMatch> 402 <kTable_SrcGamma, kSRGB_DstGamma, kNone_ColorSpa ceMatch>
383 (srcSpace, srcToDst, dstSpace)); 403 (srcSpaceXYZ, srcToDst, dstSpaceXYZ));
384 } 404 }
385 case k2Dot2Curve_SkGammaNamed: 405 case k2Dot2Curve_SkGammaNamed:
386 if (srcSpace->gammaIsLinear()) { 406 if (srcSpaceXYZ->gammaIsLinear()) {
387 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpa ceXform_XYZ 407 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpa ceXform_XYZ
388 <kLinear_SrcGamma, k2Dot2_DstGamma, kNone_ColorS paceMatch> 408 <kLinear_SrcGamma, k2Dot2_DstGamma, kNone_ColorS paceMatch>
389 (srcSpace, srcToDst, dstSpace)); 409 (srcSpaceXYZ, srcToDst, dstSpaceXYZ));
390 } else { 410 } else {
391 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpa ceXform_XYZ 411 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpa ceXform_XYZ
392 <kTable_SrcGamma, k2Dot2_DstGamma, kNone_ColorSp aceMatch> 412 <kTable_SrcGamma, k2Dot2_DstGamma, kNone_ColorSp aceMatch>
393 (srcSpace, srcToDst, dstSpace)); 413 (srcSpaceXYZ, srcToDst, dstSpaceXYZ));
394 } 414 }
395 case kLinear_SkGammaNamed: 415 case kLinear_SkGammaNamed:
396 if (srcSpace->gammaIsLinear()) { 416 if (srcSpaceXYZ->gammaIsLinear()) {
397 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpa ceXform_XYZ 417 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpa ceXform_XYZ
398 <kLinear_SrcGamma, kLinear_DstGamma, kNone_Color SpaceMatch> 418 <kLinear_SrcGamma, kLinear_DstGamma, kNone_Color SpaceMatch>
399 (srcSpace, srcToDst, dstSpace)); 419 (srcSpaceXYZ, srcToDst, dstSpaceXYZ));
400 } else { 420 } else {
401 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpa ceXform_XYZ 421 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpa ceXform_XYZ
402 <kTable_SrcGamma, kLinear_DstGamma, kNone_ColorS paceMatch> 422 <kTable_SrcGamma, kLinear_DstGamma, kNone_ColorS paceMatch>
403 (srcSpace, srcToDst, dstSpace)); 423 (srcSpaceXYZ, srcToDst, dstSpaceXYZ));
404 } 424 }
405 default: 425 default:
406 if (srcSpace->gammaIsLinear()) { 426 if (srcSpaceXYZ->gammaIsLinear()) {
407 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpa ceXform_XYZ 427 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpa ceXform_XYZ
408 <kLinear_SrcGamma, kTable_DstGamma, kNone_ColorS paceMatch> 428 <kLinear_SrcGamma, kTable_DstGamma, kNone_ColorS paceMatch>
409 (srcSpace, srcToDst, dstSpace)); 429 (srcSpaceXYZ, srcToDst, dstSpaceXYZ));
410 } else { 430 } else {
411 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpa ceXform_XYZ 431 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpa ceXform_XYZ
412 <kTable_SrcGamma, kTable_DstGamma, kNone_ColorSp aceMatch> 432 <kTable_SrcGamma, kTable_DstGamma, kNone_ColorSp aceMatch>
413 (srcSpace, srcToDst, dstSpace)); 433 (srcSpaceXYZ, srcToDst, dstSpaceXYZ));
414 } 434 }
415 } 435 }
416 case kGamut_ColorSpaceMatch: 436 case kGamut_ColorSpaceMatch:
417 switch (as_CSB(dstSpace)->gammaNamed()) { 437 switch (dstSpaceXYZ->gammaNamed()) {
418 case kSRGB_SkGammaNamed: 438 case kSRGB_SkGammaNamed:
419 if (srcSpace->gammaIsLinear()) { 439 if (srcSpaceXYZ->gammaIsLinear()) {
420 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpa ceXform_XYZ 440 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpa ceXform_XYZ
421 <kLinear_SrcGamma, kSRGB_DstGamma, kGamut_ColorS paceMatch> 441 <kLinear_SrcGamma, kSRGB_DstGamma, kGamut_ColorS paceMatch>
422 (srcSpace, srcToDst, dstSpace)); 442 (srcSpaceXYZ, srcToDst, dstSpaceXYZ));
423 } else { 443 } else {
424 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpa ceXform_XYZ 444 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpa ceXform_XYZ
425 <kTable_SrcGamma, kSRGB_DstGamma, kGamut_ColorSp aceMatch> 445 <kTable_SrcGamma, kSRGB_DstGamma, kGamut_ColorSp aceMatch>
426 (srcSpace, srcToDst, dstSpace)); 446 (srcSpaceXYZ, srcToDst, dstSpaceXYZ));
427 } 447 }
428 case k2Dot2Curve_SkGammaNamed: 448 case k2Dot2Curve_SkGammaNamed:
429 if (srcSpace->gammaIsLinear()) { 449 if (srcSpaceXYZ->gammaIsLinear()) {
430 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpa ceXform_XYZ 450 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpa ceXform_XYZ
431 <kLinear_SrcGamma, k2Dot2_DstGamma, kGamut_Color SpaceMatch> 451 <kLinear_SrcGamma, k2Dot2_DstGamma, kGamut_Color SpaceMatch>
432 (srcSpace, srcToDst, dstSpace)); 452 (srcSpaceXYZ, srcToDst, dstSpaceXYZ));
433 } else { 453 } else {
434 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpa ceXform_XYZ 454 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpa ceXform_XYZ
435 <kTable_SrcGamma, k2Dot2_DstGamma, kGamut_ColorS paceMatch> 455 <kTable_SrcGamma, k2Dot2_DstGamma, kGamut_ColorS paceMatch>
436 (srcSpace, srcToDst, dstSpace)); 456 (srcSpaceXYZ, srcToDst, dstSpaceXYZ));
437 } 457 }
438 case kLinear_SkGammaNamed: 458 case kLinear_SkGammaNamed:
439 if (srcSpace->gammaIsLinear()) { 459 if (srcSpaceXYZ->gammaIsLinear()) {
440 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpa ceXform_XYZ 460 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpa ceXform_XYZ
441 <kLinear_SrcGamma, kLinear_DstGamma, kGamut_Colo rSpaceMatch> 461 <kLinear_SrcGamma, kLinear_DstGamma, kGamut_Colo rSpaceMatch>
442 (srcSpace, srcToDst, dstSpace)); 462 (srcSpaceXYZ, srcToDst, dstSpaceXYZ));
443 } else { 463 } else {
444 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpa ceXform_XYZ 464 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpa ceXform_XYZ
445 <kTable_SrcGamma, kLinear_DstGamma, kGamut_Color SpaceMatch> 465 <kTable_SrcGamma, kLinear_DstGamma, kGamut_Color SpaceMatch>
446 (srcSpace, srcToDst, dstSpace)); 466 (srcSpaceXYZ, srcToDst, dstSpaceXYZ));
447 } 467 }
448 default: 468 default:
449 if (srcSpace->gammaIsLinear()) { 469 if (srcSpaceXYZ->gammaIsLinear()) {
450 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpa ceXform_XYZ 470 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpa ceXform_XYZ
451 <kLinear_SrcGamma, kTable_DstGamma, kGamut_Color SpaceMatch> 471 <kLinear_SrcGamma, kTable_DstGamma, kGamut_Color SpaceMatch>
452 (srcSpace, srcToDst, dstSpace)); 472 (srcSpaceXYZ, srcToDst, dstSpaceXYZ));
453 } else { 473 } else {
454 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpa ceXform_XYZ 474 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpa ceXform_XYZ
455 <kTable_SrcGamma, kTable_DstGamma, kGamut_ColorS paceMatch> 475 <kTable_SrcGamma, kTable_DstGamma, kGamut_ColorS paceMatch>
456 (srcSpace, srcToDst, dstSpace)); 476 (srcSpaceXYZ, srcToDst, dstSpaceXYZ));
457 } 477 }
458 } 478 }
459 case kFull_ColorSpaceMatch: 479 case kFull_ColorSpaceMatch:
460 switch (as_CSB(dstSpace)->gammaNamed()) { 480 switch (dstSpaceXYZ->gammaNamed()) {
461 case kSRGB_SkGammaNamed: 481 case kSRGB_SkGammaNamed:
462 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXf orm_XYZ 482 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXf orm_XYZ
463 <kTable_SrcGamma, kSRGB_DstGamma, kFull_ColorSpaceMa tch> 483 <kTable_SrcGamma, kSRGB_DstGamma, kFull_ColorSpaceMa tch>
464 (srcSpace, srcToDst, dstSpace)); 484 (srcSpaceXYZ, srcToDst, dstSpaceXYZ));
465 case k2Dot2Curve_SkGammaNamed: 485 case k2Dot2Curve_SkGammaNamed:
466 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXf orm_XYZ 486 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXf orm_XYZ
467 <kTable_SrcGamma, k2Dot2_DstGamma, kFull_ColorSpaceM atch> 487 <kTable_SrcGamma, k2Dot2_DstGamma, kFull_ColorSpaceM atch>
468 (srcSpace, srcToDst, dstSpace)); 488 (srcSpaceXYZ, srcToDst, dstSpaceXYZ));
469 case kLinear_SkGammaNamed: 489 case kLinear_SkGammaNamed:
470 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXf orm_XYZ 490 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXf orm_XYZ
471 <kLinear_SrcGamma, kLinear_DstGamma, kFull_ColorSpac eMatch> 491 <kLinear_SrcGamma, kLinear_DstGamma, kFull_ColorSpac eMatch>
472 (srcSpace, srcToDst, dstSpace)); 492 (srcSpaceXYZ, srcToDst, dstSpaceXYZ));
473 default: 493 default:
474 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXf orm_XYZ 494 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXf orm_XYZ
475 <kTable_SrcGamma, kTable_DstGamma, kFull_ColorSpaceM atch> 495 <kTable_SrcGamma, kTable_DstGamma, kFull_ColorSpaceM atch>
476 (srcSpace, srcToDst, dstSpace)); 496 (srcSpaceXYZ, srcToDst, dstSpaceXYZ));
477 } 497 }
478 default: 498 default:
479 SkASSERT(false); 499 SkASSERT(false);
480 return nullptr; 500 return nullptr;
481 } 501 }
482 } 502 }
483 503
484 //////////////////////////////////////////////////////////////////////////////// /////////////////// 504 //////////////////////////////////////////////////////////////////////////////// ///////////////////
485 505
486 static float byte_to_float(uint8_t byte) {
487 return ((float) byte) * (1.0f / 255.0f);
488 }
489
490 // Clamp to the 0-1 range.
491 static float clamp_normalized_float(float v) {
492 if (v > 1.0f) {
493 return 1.0f;
494 } else if ((v < 0.0f) || (v != v)) {
495 return 0.0f;
496 } else {
497 return v;
498 }
499 }
500
501 static void interp_3d_clut(float dst[3], float src[3], const SkColorLookUpTable* colorLUT) {
502 // Call the src components x, y, and z.
503 uint8_t maxX = colorLUT->fGridPoints[0] - 1;
504 uint8_t maxY = colorLUT->fGridPoints[1] - 1;
505 uint8_t maxZ = colorLUT->fGridPoints[2] - 1;
506
507 // An approximate index into each of the three dimensions of the table.
508 float x = src[0] * maxX;
509 float y = src[1] * maxY;
510 float z = src[2] * maxZ;
511
512 // This gives us the low index for our interpolation.
513 int ix = sk_float_floor2int(x);
514 int iy = sk_float_floor2int(y);
515 int iz = sk_float_floor2int(z);
516
517 // Make sure the low index is not also the max index.
518 ix = (maxX == ix) ? ix - 1 : ix;
519 iy = (maxY == iy) ? iy - 1 : iy;
520 iz = (maxZ == iz) ? iz - 1 : iz;
521
522 // Weighting factors for the interpolation.
523 float diffX = x - ix;
524 float diffY = y - iy;
525 float diffZ = z - iz;
526
527 // Constants to help us navigate the 3D table.
528 // Ex: Assume x = a, y = b, z = c.
529 // table[a * n001 + b * n010 + c * n100] logically equals table[a][b][c] .
530 const int n000 = 0;
531 const int n001 = 3 * colorLUT->fGridPoints[1] * colorLUT->fGridPoints[2];
532 const int n010 = 3 * colorLUT->fGridPoints[2];
533 const int n011 = n001 + n010;
534 const int n100 = 3;
535 const int n101 = n100 + n001;
536 const int n110 = n100 + n010;
537 const int n111 = n110 + n001;
538
539 // Base ptr into the table.
540 const float* ptr = &(colorLUT->table()[ix*n001 + iy*n010 + iz*n100]);
541
542 // The code below performs a tetrahedral interpolation for each of the three
543 // dst components. Once the tetrahedron containing the interpolation point is
544 // identified, the interpolation is a weighted sum of grid values at the
545 // vertices of the tetrahedron. The claim is that tetrahedral interpolation
546 // provides a more accurate color conversion.
547 // blogs.mathworks.com/steve/2006/11/24/tetrahedral-interpolation-for-colors pace-conversion/
548 //
549 // I have one test image, and visually I can't tell the difference between
550 // tetrahedral and trilinear interpolation. In terms of computation, the
551 // tetrahedral code requires more branches but less computation. The
552 // SampleICC library provides an option for the client to choose either
553 // tetrahedral or trilinear.
554 for (int i = 0; i < 3; i++) {
555 if (diffZ < diffY) {
556 if (diffZ < diffX) {
557 dst[i] = (ptr[n000] + diffZ * (ptr[n110] - ptr[n010]) +
558 diffY * (ptr[n010] - ptr[n000]) +
559 diffX * (ptr[n111] - ptr[n110]));
560 } else if (diffY < diffX) {
561 dst[i] = (ptr[n000] + diffZ * (ptr[n111] - ptr[n011]) +
562 diffY * (ptr[n011] - ptr[n001]) +
563 diffX * (ptr[n001] - ptr[n000]));
564 } else {
565 dst[i] = (ptr[n000] + diffZ * (ptr[n111] - ptr[n011]) +
566 diffY * (ptr[n010] - ptr[n000]) +
567 diffX * (ptr[n011] - ptr[n010]));
568 }
569 } else {
570 if (diffZ < diffX) {
571 dst[i] = (ptr[n000] + diffZ * (ptr[n101] - ptr[n001]) +
572 diffY * (ptr[n111] - ptr[n101]) +
573 diffX * (ptr[n001] - ptr[n000]));
574 } else if (diffY < diffX) {
575 dst[i] = (ptr[n000] + diffZ * (ptr[n100] - ptr[n000]) +
576 diffY * (ptr[n111] - ptr[n101]) +
577 diffX * (ptr[n101] - ptr[n100]));
578 } else {
579 dst[i] = (ptr[n000] + diffZ * (ptr[n100] - ptr[n000]) +
580 diffY * (ptr[n110] - ptr[n100]) +
581 diffX * (ptr[n111] - ptr[n110]));
582 }
583 }
584
585 // Increment the table ptr in order to handle the next component.
586 // Note that this is the how table is designed: all of nXXX
587 // variables are multiples of 3 because there are 3 output
588 // components.
589 ptr++;
590 }
591 }
592
593 static void handle_color_lut(uint32_t* dst, const void* vsrc, int len,
594 SkColorLookUpTable* colorLUT) {
595 const uint32_t* src = (const uint32_t*) vsrc;
596 while (len-- > 0) {
597 uint8_t r = (*src >> 0) & 0xFF,
598 g = (*src >> 8) & 0xFF,
599 b = (*src >> 16) & 0xFF;
600
601 float in[3];
602 float out[3];
603 in[0] = byte_to_float(r);
604 in[1] = byte_to_float(g);
605 in[2] = byte_to_float(b);
606 interp_3d_clut(out, in, colorLUT);
607
608 r = sk_float_round2int(255.0f * clamp_normalized_float(out[0]));
609 g = sk_float_round2int(255.0f * clamp_normalized_float(out[1]));
610 b = sk_float_round2int(255.0f * clamp_normalized_float(out[2]));
611 *dst = SkPackARGB_as_RGBA(0xFF, r, g, b);
612
613 src++;
614 dst++;
615 }
616 }
617
618 static inline void load_matrix(const float matrix[16], 506 static inline void load_matrix(const float matrix[16],
619 Sk4f& rXgXbX, Sk4f& rYgYbY, Sk4f& rZgZbZ, Sk4f& r TgTbT) { 507 Sk4f& rXgXbX, Sk4f& rYgYbY, Sk4f& rZgZbZ, Sk4f& r TgTbT) {
620 rXgXbX = Sk4f::Load(matrix + 0); 508 rXgXbX = Sk4f::Load(matrix + 0);
621 rYgYbY = Sk4f::Load(matrix + 4); 509 rYgYbY = Sk4f::Load(matrix + 4);
622 rZgZbZ = Sk4f::Load(matrix + 8); 510 rZgZbZ = Sk4f::Load(matrix + 8);
623 rTgTbT = Sk4f::Load(matrix + 12); 511 rTgTbT = Sk4f::Load(matrix + 12);
624 } 512 }
625 513
626 enum Order { 514 enum Order {
627 kRGBA_Order, 515 kRGBA_Order,
(...skipping 591 matching lines...) Expand 10 before | Expand all | Expand 10 after
1219 store_1(dst, src, rgba, a, dstTables); 1107 store_1(dst, src, rgba, a, dstTables);
1220 1108
1221 src += 1; 1109 src += 1;
1222 len -= 1; 1110 len -= 1;
1223 dst = SkTAddOffset<void>(dst, sizeOfDstPixel); 1111 dst = SkTAddOffset<void>(dst, sizeOfDstPixel);
1224 } 1112 }
1225 } 1113 }
1226 1114
1227 //////////////////////////////////////////////////////////////////////////////// /////////////////// 1115 //////////////////////////////////////////////////////////////////////////////// ///////////////////
1228 1116
1229 static inline int num_tables(SkColorSpace* space) { 1117 static inline int num_tables(SkColorSpace_XYZ* space) {
1230 switch (as_CSB(space)->gammaNamed()) { 1118 switch (space->gammaNamed()) {
1231 case kSRGB_SkGammaNamed: 1119 case kSRGB_SkGammaNamed:
1232 case k2Dot2Curve_SkGammaNamed: 1120 case k2Dot2Curve_SkGammaNamed:
1233 case kLinear_SkGammaNamed: 1121 case kLinear_SkGammaNamed:
1234 return 0; 1122 return 0;
1235 default: { 1123 default: {
1236 const SkGammas* gammas = as_CSB(space)->gammas(); 1124 const SkGammas* gammas = space->gammas();
1237 SkASSERT(gammas); 1125 SkASSERT(gammas);
1238 1126
1239 bool gammasAreMatching = (gammas->type(0) == gammas->type(1)) && 1127 bool gammasAreMatching = (gammas->type(0) == gammas->type(1)) &&
1240 (gammas->data(0) == gammas->data(1)) && 1128 (gammas->data(0) == gammas->data(1)) &&
1241 (gammas->type(0) == gammas->type(2)) && 1129 (gammas->type(0) == gammas->type(2)) &&
1242 (gammas->data(0) == gammas->data(2)); 1130 (gammas->data(0) == gammas->data(2));
1243 1131
1244 // It's likely that each component will have the same gamma. In thi s case, 1132 // It's likely that each component will have the same gamma. In thi s case,
1245 // we only need to build one table. 1133 // we only need to build one table.
1246 return gammasAreMatching ? 1 : 3; 1134 return gammasAreMatching ? 1 : 3;
1247 } 1135 }
1248 } 1136 }
1249 } 1137 }
1250 1138
1251 template <SrcGamma kSrc, DstGamma kDst, ColorSpaceMatch kCSM> 1139 template <SrcGamma kSrc, DstGamma kDst, ColorSpaceMatch kCSM>
1252 SkColorSpaceXform_XYZ<kSrc, kDst, kCSM> 1140 SkColorSpaceXform_XYZ<kSrc, kDst, kCSM>
1253 ::SkColorSpaceXform_XYZ(SkColorSpace* srcSpace, const SkMatrix44& srcToDst, SkCo lorSpace* dstSpace) 1141 ::SkColorSpaceXform_XYZ(SkColorSpace_XYZ* srcSpace, const SkMatrix44& srcToDst,
1254 : fColorLUT(sk_ref_sp((SkColorLookUpTable*) as_CSB(srcSpace)->colorLUT())) 1142 SkColorSpace_XYZ* dstSpace)
1255 { 1143 {
1256 srcToDst.asColMajorf(fSrcToDst); 1144 srcToDst.asColMajorf(fSrcToDst);
1257 1145
1258 const int numSrcTables = num_tables(srcSpace); 1146 const int numSrcTables = num_tables(srcSpace);
1259 const size_t srcEntries = numSrcTables * 256; 1147 const size_t srcEntries = numSrcTables * 256;
1260 const bool srcGammasAreMatching = (1 >= numSrcTables); 1148 const bool srcGammasAreMatching = (1 >= numSrcTables);
1261 fSrcStorage.reset(srcEntries); 1149 fSrcStorage.reset(srcEntries);
1262 build_gamma_tables(fSrcGammaTables, fSrcStorage.get(), 256, srcSpace, kToLin ear, 1150 build_gamma_tables(fSrcGammaTables, fSrcStorage.get(), 256, srcSpace, kToLin ear,
1263 srcGammasAreMatching); 1151 srcGammasAreMatching);
1264 1152
1265 const int numDstTables = num_tables(dstSpace); 1153 const int numDstTables = num_tables(dstSpace);
1266 as_CSB(dstSpace)->toDstGammaTables(fDstGammaTables, &fDstStorage, numDstTabl es); 1154 dstSpace->toDstGammaTables(fDstGammaTables, &fDstStorage, numDstTables);
1267 } 1155 }
1268 1156
1269 //////////////////////////////////////////////////////////////////////////////// /////////////////// 1157 //////////////////////////////////////////////////////////////////////////////// ///////////////////
1270 1158
1271 template <SrcFormat kSrc, DstFormat kDst, ColorSpaceMatch kCSM> 1159 template <SrcFormat kSrc, DstFormat kDst, ColorSpaceMatch kCSM>
1272 static inline bool apply_set_alpha(void* dst, const void* src, int len, SkAlphaT ype alphaType, 1160 static inline bool apply_set_alpha(void* dst, const void* src, int len, SkAlphaT ype alphaType,
1273 const float* const srcTables[3], const float matrix[16], 1161 const float* const srcTables[3], const float matrix[16],
1274 const uint8_t* const dstTables[3]) { 1162 const uint8_t* const dstTables[3]) {
1275 switch (alphaType) { 1163 switch (alphaType) {
1276 case kOpaque_SkAlphaType: 1164 case kOpaque_SkAlphaType:
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
1341 case kRGBA_F16_ColorFormat: 1229 case kRGBA_F16_ColorFormat:
1342 case kRGBA_F32_ColorFormat: 1230 case kRGBA_F32_ColorFormat:
1343 // There's still work to do to xform to linear floats. 1231 // There's still work to do to xform to linear floats.
1344 break; 1232 break;
1345 default: 1233 default:
1346 return false; 1234 return false;
1347 } 1235 }
1348 } 1236 }
1349 } 1237 }
1350 1238
1351 #if defined(GOOGLE3)
1352 // Stack frame size is limited in GOOGLE3.
1353 SkAutoSMalloc<256 * sizeof(uint32_t)> storage;
1354 #else
1355 SkAutoSMalloc<1024 * sizeof(uint32_t)> storage;
1356 #endif
1357 if (fColorLUT) {
1358 size_t storageBytes = len * sizeof(uint32_t);
1359 storage.reset(storageBytes);
1360 handle_color_lut((uint32_t*) storage.get(), src, len, fColorLUT.get());
1361 src = (const uint32_t*) storage.get();
1362 }
1363
1364 switch (dstColorFormat) { 1239 switch (dstColorFormat) {
1365 case kRGBA_8888_ColorFormat: 1240 case kRGBA_8888_ColorFormat:
1366 switch (kDst) { 1241 switch (kDst) {
1367 case kLinear_DstGamma: 1242 case kLinear_DstGamma:
1368 return apply_set_src<kSrc, kRGBA_8888_Linear_DstFormat, kCSM > 1243 return apply_set_src<kSrc, kRGBA_8888_Linear_DstFormat, kCSM >
1369 (dst, src, len, alphaType, fSrcGammaTables, fSrcToDs t, nullptr, 1244 (dst, src, len, alphaType, fSrcGammaTables, fSrcToDs t, nullptr,
1370 srcColorFormat); 1245 srcColorFormat);
1371 case kSRGB_DstGamma: 1246 case kSRGB_DstGamma:
1372 return apply_set_src<kSrc, kRGBA_8888_SRGB_DstFormat, kCSM> 1247 return apply_set_src<kSrc, kRGBA_8888_SRGB_DstFormat, kCSM>
1373 (dst, src, len, alphaType, fSrcGammaTables, fSrcToDs t, nullptr, 1248 (dst, src, len, alphaType, fSrcGammaTables, fSrcToDs t, nullptr,
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1424 } 1299 }
1425 1300
1426 bool SkColorSpaceXform::apply(ColorFormat dstColorFormat, void* dst, ColorFormat srcColorFormat, 1301 bool SkColorSpaceXform::apply(ColorFormat dstColorFormat, void* dst, ColorFormat srcColorFormat,
1427 const void* src, int len, SkAlphaType alphaType) c onst { 1302 const void* src, int len, SkAlphaType alphaType) c onst {
1428 return ((SkColorSpaceXform_Base*) this)->onApply(dstColorFormat, dst, srcCol orFormat, src, len, 1303 return ((SkColorSpaceXform_Base*) this)->onApply(dstColorFormat, dst, srcCol orFormat, src, len,
1429 alphaType); 1304 alphaType);
1430 } 1305 }
1431 1306
1432 //////////////////////////////////////////////////////////////////////////////// /////////////////// 1307 //////////////////////////////////////////////////////////////////////////////// ///////////////////
1433 1308
1434 std::unique_ptr<SkColorSpaceXform> SlowIdentityXform(SkColorSpace* space) { 1309 std::unique_ptr<SkColorSpaceXform> SlowIdentityXform(SkColorSpace_XYZ* space) {
1435 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ 1310 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_XYZ
1436 <kTable_SrcGamma, kTable_DstGamma, kNone_ColorSpaceMatch> 1311 <kTable_SrcGamma, kTable_DstGamma, kNone_ColorSpaceMatch>
1437 (space, SkMatrix::I(), space)); 1312 (space, SkMatrix::I(), space));
1438 } 1313 }
OLDNEW
« no previous file with comments | « src/core/SkColorSpace.cpp ('k') | src/core/SkColorSpaceXform_Base.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698