| Index: src/core/SkColorSpace.cpp
|
| diff --git a/src/core/SkColorSpace.cpp b/src/core/SkColorSpace.cpp
|
| index 43c424f1dca8b0cf9b004f29b22ffd1b4d1585a0..54495de9407e62d41d9c556e557c7060297f4a3b 100644
|
| --- a/src/core/SkColorSpace.cpp
|
| +++ b/src/core/SkColorSpace.cpp
|
| @@ -23,29 +23,28 @@ void SkFloat3x3::dump() const {
|
|
|
| static int32_t gUniqueColorSpaceID;
|
|
|
| -SkColorSpace::SkColorSpace(const SkFloat3& gamma, const SkFloat3x3& toXYZD50, Named named)
|
| - : fGamma(gamma)
|
| +SkColorSpace::SkColorSpace(SkGammas gammas, const SkFloat3x3& toXYZD50, Named named)
|
| + : fGammas(std::move(gammas))
|
| , fToXYZD50(toXYZD50)
|
| , fToXYZOffset({{ 0.0f, 0.0f, 0.0f }})
|
| , fUniqueID(sk_atomic_inc(&gUniqueColorSpaceID))
|
| , fNamed(named)
|
| {}
|
|
|
| -SkColorSpace::SkColorSpace(SkColorLookUpTable colorLUT, const SkFloat3& gamma,
|
| +SkColorSpace::SkColorSpace(SkColorLookUpTable colorLUT, SkGammas gammas,
|
| const SkFloat3x3& toXYZD50, const SkFloat3& toXYZOffset)
|
| : fColorLUT(std::move(colorLUT))
|
| - , fGamma(gamma)
|
| + , fGammas(std::move(gammas))
|
| , fToXYZD50(toXYZD50)
|
| , fToXYZOffset(toXYZOffset)
|
| , fUniqueID(sk_atomic_inc(&gUniqueColorSpaceID))
|
| , fNamed(kUnknown_Named)
|
| {}
|
|
|
| -sk_sp<SkColorSpace> SkColorSpace::NewRGB(const SkFloat3x3& toXYZD50, const SkFloat3& gamma) {
|
| - return sk_sp<SkColorSpace>(new SkColorSpace(gamma, toXYZD50, kUnknown_Named));
|
| +sk_sp<SkColorSpace> SkColorSpace::NewRGB(const SkFloat3x3& toXYZD50, SkGammas gammas) {
|
| + return sk_sp<SkColorSpace>(new SkColorSpace(std::move(gammas), toXYZD50, kUnknown_Named));
|
| }
|
|
|
| -const SkFloat3 gSRGB_gamma {{ 2.2f, 2.2f, 2.2f }};
|
| const SkFloat3x3 gSRGB_toXYZD50 {{
|
| 0.4358f, 0.2224f, 0.0139f, // * R
|
| 0.3853f, 0.7170f, 0.0971f, // * G
|
| @@ -55,7 +54,8 @@ const SkFloat3x3 gSRGB_toXYZD50 {{
|
| sk_sp<SkColorSpace> SkColorSpace::NewNamed(Named named) {
|
| switch (named) {
|
| case kSRGB_Named:
|
| - return sk_sp<SkColorSpace>(new SkColorSpace(gSRGB_gamma, gSRGB_toXYZD50, kSRGB_Named));
|
| + return sk_sp<SkColorSpace>(new SkColorSpace(SkGammas(2.2f, 2.2f, 2.2f), gSRGB_toXYZD50,
|
| + kSRGB_Named));
|
| default:
|
| break;
|
| }
|
| @@ -264,9 +264,8 @@ bool load_xyz(float dst[3], const uint8_t* src, size_t len) {
|
| static const uint32_t kTAG_CurveType = SkSetFourByteTag('c', 'u', 'r', 'v');
|
| static const uint32_t kTAG_ParaCurveType = SkSetFourByteTag('p', 'a', 'r', 'a');
|
|
|
| -// FIXME (msarett):
|
| -// We need to handle the possibility that the gamma curve does not correspond to 2.2f.
|
| -static bool load_gammas(float* gammas, uint32_t numGammas, const uint8_t* src, size_t len) {
|
| +bool SkColorSpace::LoadGammas(SkGammaCurve* gammas, uint32_t numGammas, const uint8_t* src,
|
| + size_t len) {
|
| for (uint32_t i = 0; i < numGammas; i++) {
|
| if (len < 12) {
|
| // FIXME (msarett):
|
| @@ -289,7 +288,7 @@ static bool load_gammas(float* gammas, uint32_t numGammas, const uint8_t* src, s
|
| // Some tags require a gamma curve, but the author doesn't actually want
|
| // to transform the data. In this case, it is common to see a curve with
|
| // a count of 0.
|
| - gammas[i] = 1.0f;
|
| + gammas[i].fValue = 1.0f;
|
| break;
|
| } else if (len < 12 + 2 * count) {
|
| SkColorSpacePrintf("gamma tag is too small (%d bytes)", len);
|
| @@ -298,27 +297,31 @@ static bool load_gammas(float* gammas, uint32_t numGammas, const uint8_t* src, s
|
|
|
| const uint16_t* table = (const uint16_t*) (src + 12);
|
| if (1 == count) {
|
| - // Table entry is the exponent (bias 256).
|
| + // The table entry is the gamma (with a bias of 256).
|
| uint16_t value = read_big_endian_short((const uint8_t*) table);
|
| - gammas[i] = value / 256.0f;
|
| + gammas[i].fValue = value / 256.0f;
|
| SkColorSpacePrintf("gamma %d %g\n", value, *gamma);
|
| break;
|
| }
|
|
|
| - // Print the interpolation table. For now, we ignore this and guess 2.2f.
|
| + // Fill in the interpolation table.
|
| + // FIXME (msarett):
|
| + // We should recognize commonly occurring tables and just set gamma to 2.2f.
|
| + gammas[i].fTableSize = count;
|
| + gammas[i].fTable = std::unique_ptr<float[]>(new float[count]);
|
| for (uint32_t j = 0; j < count; j++) {
|
| - SkColorSpacePrintf("curve[%d] %d\n", j,
|
| - read_big_endian_short((const uint8_t*) &table[j]));
|
| + gammas[i].fTable[j] =
|
| + (read_big_endian_short((const uint8_t*) &table[j])) / 65535.0f;
|
| }
|
| -
|
| - gammas[i] = 2.2f;
|
| break;
|
| }
|
| case kTAG_ParaCurveType:
|
| // Guess 2.2f.
|
| + // FIXME (msarett): Handle parametric curves.
|
| SkColorSpacePrintf("parametric curve\n");
|
| - gammas[i] = 2.2f;
|
| + gammas[i].fValue = 2.2f;
|
|
|
| + // Determine the size of the parametric curve tag.
|
| switch(read_big_endian_short(src + 8)) {
|
| case 0:
|
| tagBytes = 12 + 4;
|
| @@ -358,28 +361,19 @@ static bool load_gammas(float* gammas, uint32_t numGammas, const uint8_t* src, s
|
| }
|
| }
|
|
|
| - // If all of the gammas we encounter are 1.0f, indicate that we failed to load gammas.
|
| - // There is no need to apply a gamma of 1.0f.
|
| - for (uint32_t i = 0; i < numGammas; i++) {
|
| - if (1.0f != gammas[i]) {
|
| - return true;
|
| - }
|
| - }
|
| -
|
| - return false;
|
| + return true;
|
| }
|
|
|
| static const uint32_t kTAG_AtoBType = SkSetFourByteTag('m', 'A', 'B', ' ');
|
|
|
| -bool load_color_lut(SkColorLookUpTable* colorLUT, uint32_t inputChannels, uint32_t outputChannels,
|
| - const uint8_t* src, size_t len) {
|
| +bool SkColorSpace::LoadColorLUT(SkColorLookUpTable* colorLUT, uint32_t inputChannels,
|
| + uint32_t outputChannels, const uint8_t* src, size_t len) {
|
| if (len < 20) {
|
| SkColorSpacePrintf("Color LUT tag is too small (%d bytes).", len);
|
| return false;
|
| }
|
|
|
| - SkASSERT(inputChannels <= SkColorLookUpTable::kMaxChannels &&
|
| - outputChannels <= SkColorLookUpTable::kMaxChannels);
|
| + SkASSERT(inputChannels <= SkColorLookUpTable::kMaxChannels && 3 == outputChannels);
|
| colorLUT->fInputChannels = inputChannels;
|
| colorLUT->fOutputChannels = outputChannels;
|
| uint32_t numEntries = 1;
|
| @@ -441,8 +435,8 @@ bool load_matrix(SkFloat3x3* toXYZ, SkFloat3* toXYZOffset, const uint8_t* src, s
|
| return true;
|
| }
|
|
|
| -bool load_a2b0(SkColorLookUpTable* colorLUT, SkFloat3* gamma, SkFloat3x3* toXYZ,
|
| - SkFloat3* toXYZOffset, const uint8_t* src, size_t len) {
|
| +bool SkColorSpace::LoadA2B0(SkColorLookUpTable* colorLUT, SkGammas* gammas, SkFloat3x3* toXYZ,
|
| + SkFloat3* toXYZOffset, const uint8_t* src, size_t len) {
|
| if (len < 32) {
|
| SkColorSpacePrintf("A to B tag is too small (%d bytes).", len);
|
| return false;
|
| @@ -460,7 +454,7 @@ bool load_a2b0(SkColorLookUpTable* colorLUT, SkFloat3* gamma, SkFloat3x3* toXYZ,
|
| uint8_t inputChannels = src[8];
|
| uint8_t outputChannels = src[9];
|
| if (0 == inputChannels || inputChannels > SkColorLookUpTable::kMaxChannels ||
|
| - 0 < outputChannels || outputChannels > SkColorLookUpTable::kMaxChannels) {
|
| + 3 != outputChannels) {
|
| // The color LUT assumes that there are at most 16 input channels. For RGB
|
| // profiles, output channels should be 3.
|
| SkColorSpacePrintf("Too many input or output channels in A to B tag.\n");
|
| @@ -483,16 +477,16 @@ bool load_a2b0(SkColorLookUpTable* colorLUT, SkFloat3* gamma, SkFloat3x3* toXYZ,
|
|
|
| uint32_t offsetToColorLUT = read_big_endian_int(src + 24);
|
| if (0 != offsetToColorLUT && offsetToColorLUT < len) {
|
| - if (!load_color_lut(colorLUT, inputChannels, outputChannels, src + offsetToColorLUT,
|
| - len - offsetToColorLUT)) {
|
| + if (!SkColorSpace::LoadColorLUT(colorLUT, inputChannels, outputChannels,
|
| + src + offsetToColorLUT, len - offsetToColorLUT)) {
|
| SkColorSpacePrintf("Failed to read color LUT from A to B tag.\n");
|
| }
|
| }
|
|
|
| uint32_t offsetToMCurves = read_big_endian_int(src + 20);
|
| if (0 != offsetToMCurves && offsetToMCurves < len) {
|
| - if (!load_gammas(gamma->fVec, outputChannels, src + offsetToMCurves, len - offsetToMCurves))
|
| - {
|
| + if (!SkColorSpace::LoadGammas(&gammas->fRed, outputChannels, src + offsetToMCurves,
|
| + len - offsetToMCurves)) {
|
| SkColorSpacePrintf("Failed to read M curves from A to B tag.\n");
|
| }
|
| }
|
| @@ -567,42 +561,39 @@ sk_sp<SkColorSpace> SkColorSpace::NewICC(const void* base, size_t len) {
|
|
|
| // It is not uncommon to see missing or empty gamma tags. This indicates
|
| // that we should use unit gamma.
|
| - SkFloat3 gamma {{ 1.0f, 1.0f, 1.0f }};
|
| + SkGammas gammas;
|
| r = ICCTag::Find(tags.get(), tagCount, kTAG_rTRC);
|
| g = ICCTag::Find(tags.get(), tagCount, kTAG_gTRC);
|
| b = ICCTag::Find(tags.get(), tagCount, kTAG_bTRC);
|
| - if (!r ||
|
| - !load_gammas(&gamma.fVec[0], 1, r->addr((const uint8_t*) base), r->fLength))
|
| - {
|
| + if (!r || !SkColorSpace::LoadGammas(&gammas.fRed, 1,
|
| + r->addr((const uint8_t*) base), r->fLength)) {
|
| SkColorSpacePrintf("Failed to read R gamma tag.\n");
|
| }
|
| - if (!g ||
|
| - !load_gammas(&gamma.fVec[1], 1, g->addr((const uint8_t*) base), g->fLength))
|
| - {
|
| + if (!g || !SkColorSpace::LoadGammas(&gammas.fGreen, 1,
|
| + g->addr((const uint8_t*) base), g->fLength)) {
|
| SkColorSpacePrintf("Failed to read G gamma tag.\n");
|
| }
|
| - if (!b ||
|
| - !load_gammas(&gamma.fVec[2], 1, b->addr((const uint8_t*) base), b->fLength))
|
| - {
|
| + if (!b || !SkColorSpace::LoadGammas(&gammas.fBlue, 1,
|
| + b->addr((const uint8_t*) base), b->fLength)) {
|
| SkColorSpacePrintf("Failed to read B gamma tag.\n");
|
| }
|
| - return SkColorSpace::NewRGB(toXYZ, gamma);
|
| + return SkColorSpace::NewRGB(toXYZ, std::move(gammas));
|
| }
|
|
|
| // Recognize color profile specified by A2B0 tag.
|
| const ICCTag* a2b0 = ICCTag::Find(tags.get(), tagCount, kTAG_A2B0);
|
| if (a2b0) {
|
| SkColorLookUpTable colorLUT;
|
| - SkFloat3 gamma;
|
| + SkGammas gammas;
|
| SkFloat3x3 toXYZ;
|
| SkFloat3 toXYZOffset;
|
| - if (!load_a2b0(&colorLUT, &gamma, &toXYZ, &toXYZOffset,
|
| - a2b0->addr((const uint8_t*) base), a2b0->fLength)) {
|
| + if (!SkColorSpace::LoadA2B0(&colorLUT, &gammas, &toXYZ, &toXYZOffset,
|
| + a2b0->addr((const uint8_t*) base), a2b0->fLength)) {
|
| return_null("Failed to parse A2B0 tag");
|
| }
|
|
|
| - return sk_sp<SkColorSpace>(new SkColorSpace(std::move(colorLUT), gamma, toXYZ,
|
| - toXYZOffset));
|
| + return sk_sp<SkColorSpace>(new SkColorSpace(std::move(colorLUT), std::move(gammas),
|
| + toXYZ, toXYZOffset));
|
| }
|
|
|
| }
|
|
|