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; |