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

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

Issue 2027413002: Recognize common parametric gamma (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: 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 | « no previous file | no next file » | 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 "SkColorSpace.h" 8 #include "SkColorSpace.h"
9 #include "SkColorSpace_Base.h" 9 #include "SkColorSpace_Base.h"
10 #include "SkEndian.h" 10 #include "SkEndian.h"
(...skipping 465 matching lines...) Expand 10 before | Expand all | Expand 10 after
476 476
477 // Otherwise, fill in the interpolation table. 477 // Otherwise, fill in the interpolation table.
478 gammas[i].fTableSize = count; 478 gammas[i].fTableSize = count;
479 gammas[i].fTable = std::unique_ptr<float[]>(new float[count]); 479 gammas[i].fTable = std::unique_ptr<float[]>(new float[count]);
480 for (uint32_t j = 0; j < count; j++) { 480 for (uint32_t j = 0; j < count; j++) {
481 gammas[i].fTable[j] = 481 gammas[i].fTable[j] =
482 (read_big_endian_short((const uint8_t*) &table[j])) / 65535.0f; 482 (read_big_endian_short((const uint8_t*) &table[j])) / 65535.0f;
483 } 483 }
484 break; 484 break;
485 } 485 }
486 case kTAG_ParaCurveType: 486 case kTAG_ParaCurveType: {
487 // Determine the format of the parametric curve tag. 487 // Determine the format of the parametric curve tag.
488 switch(read_big_endian_short(src + 8)) { 488 uint16_t format = read_big_endian_short(src + 8);
scroggo 2016/06/01 21:23:12 Do these formats have names you can use?
msarett 2016/06/01 21:26:13 They don't, but that'd be nice. I may name them i
489 case 0: { 489 if (0 == format) {
490 tagBytes = 12 + 4; 490 tagBytes = 12 + 4;
491 if (len < tagBytes) { 491 if (len < tagBytes) {
492 SkColorSpacePrintf("gamma tag is too small (%d bytes )", len); 492 SkColorSpacePrintf("gamma tag is too small (%d bytes)", len);
493 return false; 493 return false;
494 }
495
496 // Y = X^g
497 int32_t g = read_big_endian_int(src + 12);
498 gammas[i].fValue = SkFixedToFloat(g);
499 break;
500 } 494 }
501 495
496 // Y = X^g
497 int32_t g = read_big_endian_int(src + 12);
498 gammas[i].fValue = SkFixedToFloat(g);
499 } else {
502 // Here's where the real parametric gammas start. There are many 500 // Here's where the real parametric gammas start. There are many
503 // permutations of the same equations. 501 // permutations of the same equations.
504 // 502 //
505 // Y = (aX + b)^g + c for X >= d 503 // Y = (aX + b)^g + c for X >= d
506 // Y = eX + f otherwise 504 // Y = eX + f otherwise
507 // 505 //
508 // We will fill in with zeros as necessary to always match t he above form. 506 // We will fill in with zeros as necessary to always match t he above form.
509 // Note that there is no need to actually write zero, since the struct is 507 float g = 0.0f, a = 0.0f, b = 0.0f, c = 0.0f, d = 0.0f, e = 0.0f, f = 0.0f;
510 // zero initialized. 508 switch(format) {
511 case 1: { 509 case 1: {
512 tagBytes = 12 + 12; 510 tagBytes = 12 + 12;
513 if (len < tagBytes) { 511 if (len < tagBytes) {
514 SkColorSpacePrintf("gamma tag is too small (%d bytes )", len); 512 SkColorSpacePrintf("gamma tag is too small (%d b ytes)", len);
513 return false;
514 }
515
516 // Y = (aX + b)^g for X >= -b/a
517 // Y = 0 otherwise
518 g = SkFixedToFloat(read_big_endian_int(src + 12));
519 a = SkFixedToFloat(read_big_endian_int(src + 16));
520 b = SkFixedToFloat(read_big_endian_int(src + 20));
521 d = -b / a;
522 break;
523 }
524 case 2:
525 tagBytes = 12 + 16;
526 if (len < tagBytes) {
527 SkColorSpacePrintf("gamma tag is too small (%d b ytes)", len);
528 return false;
529 }
530
531 // Y = (aX + b)^g + c for X >= -b/a
532 // Y = c otherwise
533 g = SkFixedToFloat(read_big_endian_int(src + 12));
534 a = SkFixedToFloat(read_big_endian_int(src + 16));
535 b = SkFixedToFloat(read_big_endian_int(src + 20));
536 c = SkFixedToFloat(read_big_endian_int(src + 24));
537 d = -b / a;
538 f = c;
539 break;
540 case 3:
541 tagBytes = 12 + 20;
542 if (len < tagBytes) {
543 SkColorSpacePrintf("gamma tag is too small (%d b ytes)", len);
544 return false;
545 }
546
547 // Y = (aX + b)^g for X >= d
548 // Y = cX otherwise
549 g = SkFixedToFloat(read_big_endian_int(src + 12));
550 a = SkFixedToFloat(read_big_endian_int(src + 16));
551 b = SkFixedToFloat(read_big_endian_int(src + 20));
552 d = SkFixedToFloat(read_big_endian_int(src + 28));
553 e = SkFixedToFloat(read_big_endian_int(src + 24));
554 break;
555 case 4:
556 tagBytes = 12 + 28;
557 if (len < tagBytes) {
558 SkColorSpacePrintf("gamma tag is too small (%d b ytes)", len);
559 return false;
560 }
561
562 // Y = (aX + b)^g + c for X >= d
563 // Y = eX + f otherwise
564 // NOTE: The ICC spec writes "cX" in place of "eX" b ut I think
565 // it's a typo.
566 g = SkFixedToFloat(read_big_endian_int(src + 12));
567 a = SkFixedToFloat(read_big_endian_int(src + 16));
568 b = SkFixedToFloat(read_big_endian_int(src + 20));
569 c = SkFixedToFloat(read_big_endian_int(src + 24));
570 d = SkFixedToFloat(read_big_endian_int(src + 28));
571 e = SkFixedToFloat(read_big_endian_int(src + 32));
572 f = SkFixedToFloat(read_big_endian_int(src + 36));
573 break;
574 default:
575 SkColorSpacePrintf("Invalid parametric curve type\n" );
515 return false; 576 return false;
516 } 577 }
517 578
518 // Y = (aX + b)^g for X >= -b/a 579 // Recognize and simplify a very common parametric represent ation of sRGB gamma.
519 // Y = 0 otherwise 580 if (color_space_almost_equal(0.9479f, a) &&
msarett 2016/06/01 21:01:19 Of my set of 10k jpegs with ICC profiles, 500 of t
520 gammas[i].fG = SkFixedToFloat(read_big_endian_int(src + 12)); 581 color_space_almost_equal(0.0521f, b) &&
521 gammas[i].fA = SkFixedToFloat(read_big_endian_int(src + 16)); 582 color_space_almost_equal(0.0000f, c) &&
522 gammas[i].fB = SkFixedToFloat(read_big_endian_int(src + 20)); 583 color_space_almost_equal(0.0405f, d) &&
523 gammas[i].fD = -gammas[i].fB / gammas[i].fA; 584 color_space_almost_equal(0.0774f, e) &&
524 break; 585 color_space_almost_equal(0.0000f, f) &&
586 color_space_almost_equal(2.4000f, g)) {
587 gammas[i].fValue = 2.2f;
588 } else {
589 gammas[i].fG = g;
590 gammas[i].fA = a;
591 gammas[i].fB = b;
592 gammas[i].fC = c;
593 gammas[i].fD = d;
594 gammas[i].fE = e;
595 gammas[i].fF = f;
525 } 596 }
526 case 2: 597 }
527 tagBytes = 12 + 16;
528 if (len < tagBytes) {
529 SkColorSpacePrintf("gamma tag is too small (%d bytes )", len);
530 return false;
531 }
532 598
533 // Y = (aX + b)^g + c for X >= -b/a
534 // Y = c otherwise
535 gammas[i].fG = SkFixedToFloat(read_big_endian_int(src + 12));
536 gammas[i].fA = SkFixedToFloat(read_big_endian_int(src + 16));
537 gammas[i].fB = SkFixedToFloat(read_big_endian_int(src + 20));
538 gammas[i].fC = SkFixedToFloat(read_big_endian_int(src + 24));
539 gammas[i].fD = -gammas[i].fB / gammas[i].fA;
540 gammas[i].fF = gammas[i].fC;
541 break;
542 case 3:
543 tagBytes = 12 + 20;
544 if (len < tagBytes) {
545 SkColorSpacePrintf("gamma tag is too small (%d bytes )", len);
546 return false;
547 }
548
549 // Y = (aX + b)^g for X >= d
550 // Y = cX otherwise
551 gammas[i].fG = SkFixedToFloat(read_big_endian_int(src + 12));
552 gammas[i].fA = SkFixedToFloat(read_big_endian_int(src + 16));
553 gammas[i].fB = SkFixedToFloat(read_big_endian_int(src + 20));
554 gammas[i].fD = SkFixedToFloat(read_big_endian_int(src + 28));
555 gammas[i].fE = SkFixedToFloat(read_big_endian_int(src + 24));
556 break;
557 case 4:
558 tagBytes = 12 + 28;
559 if (len < tagBytes) {
560 SkColorSpacePrintf("gamma tag is too small (%d bytes )", len);
561 return false;
562 }
563
564 // Y = (aX + b)^g + c for X >= d
565 // Y = eX + f otherwise
566 // NOTE: The ICC spec writes "cX" instead of "eX" but I think it's a typo.
567 gammas[i].fG = SkFixedToFloat(read_big_endian_int(src + 12));
568 gammas[i].fA = SkFixedToFloat(read_big_endian_int(src + 16));
569 gammas[i].fB = SkFixedToFloat(read_big_endian_int(src + 20));
570 gammas[i].fC = SkFixedToFloat(read_big_endian_int(src + 24));
571 gammas[i].fD = SkFixedToFloat(read_big_endian_int(src + 28));
572 gammas[i].fE = SkFixedToFloat(read_big_endian_int(src + 32));
573 gammas[i].fF = SkFixedToFloat(read_big_endian_int(src + 36));
574 break;
575 default:
576 SkColorSpacePrintf("Invalid parametric curve type\n");
577 return false;
578 }
579 break; 599 break;
600 }
580 default: 601 default:
581 SkColorSpacePrintf("Unsupported gamma tag type %d\n", type); 602 SkColorSpacePrintf("Unsupported gamma tag type %d\n", type);
582 return false; 603 return false;
583 } 604 }
584 605
585 // Adjust src and len if there is another gamma curve to load. 606 // Adjust src and len if there is another gamma curve to load.
586 if (i != numGammas - 1) { 607 if (i != numGammas - 1) {
587 // Each curve is padded to 4-byte alignment. 608 // Each curve is padded to 4-byte alignment.
588 tagBytes = SkAlign4(tagBytes); 609 tagBytes = SkAlign4(tagBytes);
589 if (len < tagBytes) { 610 if (len < tagBytes) {
(...skipping 481 matching lines...) Expand 10 before | Expand all | Expand 10 after
1071 ptr32[4] = SkEndian_SwapBE32(0x000116cc); 1092 ptr32[4] = SkEndian_SwapBE32(0x000116cc);
1072 ptr += kTAG_XYZ_Bytes; 1093 ptr += kTAG_XYZ_Bytes;
1073 1094
1074 // Write copyright tag 1095 // Write copyright tag
1075 memcpy(ptr, gEmptyTextTag, sizeof(gEmptyTextTag)); 1096 memcpy(ptr, gEmptyTextTag, sizeof(gEmptyTextTag));
1076 1097
1077 // TODO (msarett): Should we try to hold onto the data so we can return imme diately if 1098 // TODO (msarett): Should we try to hold onto the data so we can return imme diately if
1078 // the client calls again? 1099 // the client calls again?
1079 return SkData::MakeFromMalloc(profile.release(), kICCProfileSize); 1100 return SkData::MakeFromMalloc(profile.release(), kICCProfileSize);
1080 } 1101 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698