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

Unified 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, 7 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/core/SkColorSpace.cpp
diff --git a/src/core/SkColorSpace.cpp b/src/core/SkColorSpace.cpp
index 3ca131d42782d4a40b519c6e4c3ddd2eee2a40ac..18b07bca289860dbcea49b4395a67d870ad85027 100644
--- a/src/core/SkColorSpace.cpp
+++ b/src/core/SkColorSpace.cpp
@@ -483,22 +483,20 @@ bool load_gammas(SkGammaCurve* gammas, uint32_t numGammas, const uint8_t* src, s
}
break;
}
- case kTAG_ParaCurveType:
+ case kTAG_ParaCurveType: {
// Determine the format of the parametric curve tag.
- switch(read_big_endian_short(src + 8)) {
- case 0: {
- tagBytes = 12 + 4;
- if (len < tagBytes) {
- SkColorSpacePrintf("gamma tag is too small (%d bytes)", len);
- return false;
- }
-
- // Y = X^g
- int32_t g = read_big_endian_int(src + 12);
- gammas[i].fValue = SkFixedToFloat(g);
- break;
+ 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
+ if (0 == format) {
+ tagBytes = 12 + 4;
+ if (len < tagBytes) {
+ SkColorSpacePrintf("gamma tag is too small (%d bytes)", len);
+ return false;
}
+ // Y = X^g
+ int32_t g = read_big_endian_int(src + 12);
+ gammas[i].fValue = SkFixedToFloat(g);
+ } else {
// Here's where the real parametric gammas start. There are many
// permutations of the same equations.
//
@@ -506,77 +504,100 @@ bool load_gammas(SkGammaCurve* gammas, uint32_t numGammas, const uint8_t* src, s
// Y = eX + f otherwise
//
// We will fill in with zeros as necessary to always match the above form.
- // Note that there is no need to actually write zero, since the struct is
- // zero initialized.
- case 1: {
- tagBytes = 12 + 12;
- if (len < tagBytes) {
- SkColorSpacePrintf("gamma tag is too small (%d bytes)", len);
- return false;
- }
-
- // Y = (aX + b)^g for X >= -b/a
- // Y = 0 otherwise
- gammas[i].fG = SkFixedToFloat(read_big_endian_int(src + 12));
- gammas[i].fA = SkFixedToFloat(read_big_endian_int(src + 16));
- gammas[i].fB = SkFixedToFloat(read_big_endian_int(src + 20));
- gammas[i].fD = -gammas[i].fB / gammas[i].fA;
- break;
- }
- case 2:
- tagBytes = 12 + 16;
- if (len < tagBytes) {
- SkColorSpacePrintf("gamma tag is too small (%d bytes)", len);
- return false;
- }
-
- // Y = (aX + b)^g + c for X >= -b/a
- // Y = c otherwise
- gammas[i].fG = SkFixedToFloat(read_big_endian_int(src + 12));
- gammas[i].fA = SkFixedToFloat(read_big_endian_int(src + 16));
- gammas[i].fB = SkFixedToFloat(read_big_endian_int(src + 20));
- gammas[i].fC = SkFixedToFloat(read_big_endian_int(src + 24));
- gammas[i].fD = -gammas[i].fB / gammas[i].fA;
- gammas[i].fF = gammas[i].fC;
- break;
- case 3:
- tagBytes = 12 + 20;
- if (len < tagBytes) {
- SkColorSpacePrintf("gamma tag is too small (%d bytes)", len);
- return false;
+ float g = 0.0f, a = 0.0f, b = 0.0f, c = 0.0f, d = 0.0f, e = 0.0f, f = 0.0f;
+ switch(format) {
+ case 1: {
+ tagBytes = 12 + 12;
+ if (len < tagBytes) {
+ SkColorSpacePrintf("gamma tag is too small (%d bytes)", len);
+ return false;
+ }
+
+ // Y = (aX + b)^g for X >= -b/a
+ // Y = 0 otherwise
+ g = SkFixedToFloat(read_big_endian_int(src + 12));
+ a = SkFixedToFloat(read_big_endian_int(src + 16));
+ b = SkFixedToFloat(read_big_endian_int(src + 20));
+ d = -b / a;
+ break;
}
-
- // Y = (aX + b)^g for X >= d
- // Y = cX otherwise
- gammas[i].fG = SkFixedToFloat(read_big_endian_int(src + 12));
- gammas[i].fA = SkFixedToFloat(read_big_endian_int(src + 16));
- gammas[i].fB = SkFixedToFloat(read_big_endian_int(src + 20));
- gammas[i].fD = SkFixedToFloat(read_big_endian_int(src + 28));
- gammas[i].fE = SkFixedToFloat(read_big_endian_int(src + 24));
- break;
- case 4:
- tagBytes = 12 + 28;
- if (len < tagBytes) {
- SkColorSpacePrintf("gamma tag is too small (%d bytes)", len);
+ case 2:
+ tagBytes = 12 + 16;
+ if (len < tagBytes) {
+ SkColorSpacePrintf("gamma tag is too small (%d bytes)", len);
+ return false;
+ }
+
+ // Y = (aX + b)^g + c for X >= -b/a
+ // Y = c otherwise
+ g = SkFixedToFloat(read_big_endian_int(src + 12));
+ a = SkFixedToFloat(read_big_endian_int(src + 16));
+ b = SkFixedToFloat(read_big_endian_int(src + 20));
+ c = SkFixedToFloat(read_big_endian_int(src + 24));
+ d = -b / a;
+ f = c;
+ break;
+ case 3:
+ tagBytes = 12 + 20;
+ if (len < tagBytes) {
+ SkColorSpacePrintf("gamma tag is too small (%d bytes)", len);
+ return false;
+ }
+
+ // Y = (aX + b)^g for X >= d
+ // Y = cX otherwise
+ g = SkFixedToFloat(read_big_endian_int(src + 12));
+ a = SkFixedToFloat(read_big_endian_int(src + 16));
+ b = SkFixedToFloat(read_big_endian_int(src + 20));
+ d = SkFixedToFloat(read_big_endian_int(src + 28));
+ e = SkFixedToFloat(read_big_endian_int(src + 24));
+ break;
+ case 4:
+ tagBytes = 12 + 28;
+ if (len < tagBytes) {
+ SkColorSpacePrintf("gamma tag is too small (%d bytes)", len);
+ return false;
+ }
+
+ // Y = (aX + b)^g + c for X >= d
+ // Y = eX + f otherwise
+ // NOTE: The ICC spec writes "cX" in place of "eX" but I think
+ // it's a typo.
+ g = SkFixedToFloat(read_big_endian_int(src + 12));
+ a = SkFixedToFloat(read_big_endian_int(src + 16));
+ b = SkFixedToFloat(read_big_endian_int(src + 20));
+ c = SkFixedToFloat(read_big_endian_int(src + 24));
+ d = SkFixedToFloat(read_big_endian_int(src + 28));
+ e = SkFixedToFloat(read_big_endian_int(src + 32));
+ f = SkFixedToFloat(read_big_endian_int(src + 36));
+ break;
+ default:
+ SkColorSpacePrintf("Invalid parametric curve type\n");
return false;
- }
+ }
- // Y = (aX + b)^g + c for X >= d
- // Y = eX + f otherwise
- // NOTE: The ICC spec writes "cX" instead of "eX" but I think it's a typo.
- gammas[i].fG = SkFixedToFloat(read_big_endian_int(src + 12));
- gammas[i].fA = SkFixedToFloat(read_big_endian_int(src + 16));
- gammas[i].fB = SkFixedToFloat(read_big_endian_int(src + 20));
- gammas[i].fC = SkFixedToFloat(read_big_endian_int(src + 24));
- gammas[i].fD = SkFixedToFloat(read_big_endian_int(src + 28));
- gammas[i].fE = SkFixedToFloat(read_big_endian_int(src + 32));
- gammas[i].fF = SkFixedToFloat(read_big_endian_int(src + 36));
- break;
- default:
- SkColorSpacePrintf("Invalid parametric curve type\n");
- return false;
+ // Recognize and simplify a very common parametric representation of sRGB gamma.
+ 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
+ color_space_almost_equal(0.0521f, b) &&
+ color_space_almost_equal(0.0000f, c) &&
+ color_space_almost_equal(0.0405f, d) &&
+ color_space_almost_equal(0.0774f, e) &&
+ color_space_almost_equal(0.0000f, f) &&
+ color_space_almost_equal(2.4000f, g)) {
+ gammas[i].fValue = 2.2f;
+ } else {
+ gammas[i].fG = g;
+ gammas[i].fA = a;
+ gammas[i].fB = b;
+ gammas[i].fC = c;
+ gammas[i].fD = d;
+ gammas[i].fE = e;
+ gammas[i].fF = f;
+ }
}
+
break;
+ }
default:
SkColorSpacePrintf("Unsupported gamma tag type %d\n", type);
return false;
« 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