diff options
author | Mike Klein <mtklein@google.com> | 2018-05-22 13:47:52 +0000 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-05-22 14:17:15 +0000 |
commit | 5b58b7c14c4405163e2af68dd3951a83fa1dabf2 (patch) | |
tree | f6d940bd35e271e139613a23e295b47dd4da631b /src | |
parent | 89735a0f47d2a06542d966a383dcba9f7a00d675 (diff) |
Reland "strip down SkICC.cpp"
This reverts commit 27fe397bc0cc1b091f9f85863c62b88156239cf0.
Reason for revert: time to fly.
Original change's description:
> Revert "strip down SkICC.cpp"
>
> This reverts commit eab50eb9c6117c2a9d0e5648f89cebbb4dbd9d30
> and this tiny bit of e61b969a07ba3ebe9e47e61381ad16c5d2c549a2:
>
> https://skia-review.googlesource.com/c/skia/+/127122/3/tests/ICCTest.cpp
>
> Change-Id: I4306e5118a4e5eb88c05078186a28bd443fd76f7
> Reviewed-on: https://skia-review.googlesource.com/127305
> Reviewed-by: Mike Klein <mtklein@chromium.org>
> Commit-Queue: Mike Klein <mtklein@chromium.org>
TBR=mtklein@chromium.org,brianosman@google.com
# Not skipping CQ checks because original CL landed > 1 day ago.
Change-Id: I93a6cfb66f0da0e098fdcb77ac1cd619e41614b1
Reviewed-on: https://skia-review.googlesource.com/129446
Reviewed-by: Mike Klein <mtklein@google.com>
Commit-Queue: Mike Klein <mtklein@google.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/core/SkICC.cpp | 213 | ||||
-rw-r--r-- | src/core/SkICCPriv.h | 7 | ||||
-rw-r--r-- | src/images/SkImageEncoderFns.h | 2 |
3 files changed, 30 insertions, 192 deletions
diff --git a/src/core/SkICC.cpp b/src/core/SkICC.cpp index 3a77dfc200..aa9c45e50b 100644 --- a/src/core/SkICC.cpp +++ b/src/core/SkICC.cpp @@ -7,134 +7,13 @@ #include "SkAutoMalloc.h" #include "SkColorSpacePriv.h" -#include "SkColorSpaceXformPriv.h" -#include "SkColorSpace_XYZ.h" #include "SkEndian.h" #include "SkFixed.h" #include "SkICC.h" #include "SkICCPriv.h" #include "SkMD5.h" -#include "SkString.h" #include "SkUtils.h" -SkICC::SkICC(sk_sp<SkColorSpace> colorSpace) - : fColorSpace(std::move(colorSpace)) -{} - -sk_sp<SkICC> SkICC::Make(const void* ptr, size_t len) { - sk_sp<SkColorSpace> colorSpace = SkColorSpace::MakeICC(ptr, len); - if (!colorSpace) { - return nullptr; - } - - return sk_sp<SkICC>(new SkICC(std::move(colorSpace))); -} - -bool SkICC::toXYZD50(SkMatrix44* toXYZD50) const { - return fColorSpace->toXYZD50(toXYZD50); -} - -bool SkICC::isNumericalTransferFn(SkColorSpaceTransferFn* coeffs) const { - return fColorSpace->isNumericalTransferFn(coeffs); -} - -static const int kDefaultTableSize = 512; // Arbitrary - -void fn_to_table(float* tablePtr, const SkColorSpaceTransferFn& fn) { - // Y = (aX + b)^g + e for X >= d - // Y = cX + f otherwise - for (int i = 0; i < kDefaultTableSize; i++) { - float x = ((float) i) / ((float) (kDefaultTableSize - 1)); - if (x >= fn.fD) { - tablePtr[i] = clamp_0_1(powf(fn.fA * x + fn.fB, fn.fG) + fn.fE); - } else { - tablePtr[i] = clamp_0_1(fn.fC * x + fn.fF); - } - } -} - -void copy_to_table(float* tablePtr, const SkGammas* gammas, int index) { - SkASSERT(gammas->isTable(index)); - const float* ptr = gammas->table(index); - const size_t bytes = gammas->tableSize(index) * sizeof(float); - memcpy(tablePtr, ptr, bytes); -} - -bool SkICC::rawTransferFnData(Tables* tables) const { - if (!fColorSpace->toXYZD50()) { - return false; // Can't even dream of handling A2B here... - } - SkColorSpace_XYZ* colorSpace = (SkColorSpace_XYZ*) fColorSpace.get(); - - SkColorSpaceTransferFn fn; - if (this->isNumericalTransferFn(&fn)) { - tables->fStorage = SkData::MakeUninitialized(kDefaultTableSize * sizeof(float)); - fn_to_table((float*) tables->fStorage->writable_data(), fn); - tables->fRed.fOffset = tables->fGreen.fOffset = tables->fBlue.fOffset = 0; - tables->fRed.fCount = tables->fGreen.fCount = tables->fBlue.fCount = kDefaultTableSize; - return true; - } - - const SkGammas* gammas = colorSpace->gammas(); - SkASSERT(gammas); - if (gammas->allChannelsSame()) { - SkASSERT(gammas->isTable(0)); - tables->fStorage = SkData::MakeUninitialized(gammas->tableSize(0) * sizeof(float)); - copy_to_table((float*) tables->fStorage->writable_data(), gammas, 0); - tables->fRed.fOffset = tables->fGreen.fOffset = tables->fBlue.fOffset = 0; - tables->fRed.fCount = tables->fGreen.fCount = tables->fBlue.fCount = gammas->tableSize(0); - return true; - } - - // Determine the storage size. - size_t storageSize = 0; - for (int i = 0; i < 3; i++) { - if (gammas->isTable(i)) { - storageSize += gammas->tableSize(i) * sizeof(float); - } else { - storageSize += kDefaultTableSize * sizeof(float); - } - } - - // Fill in the tables. - tables->fStorage = SkData::MakeUninitialized(storageSize); - float* ptr = (float*) tables->fStorage->writable_data(); - size_t offset = 0; - Channel rgb[3]; - for (int i = 0; i < 3; i++) { - if (gammas->isTable(i)) { - copy_to_table(ptr, gammas, i); - rgb[i].fOffset = offset; - rgb[i].fCount = gammas->tableSize(i); - offset += rgb[i].fCount * sizeof(float); - ptr += rgb[i].fCount; - continue; - } - - if (gammas->isNamed(i)) { - SkAssertResult(named_to_parametric(&fn, gammas->data(i).fNamed)); - } else if (gammas->isValue(i)) { - value_to_parametric(&fn, gammas->data(i).fValue); - } else { - SkASSERT(gammas->isParametric(i)); - fn = gammas->params(i); - } - - fn_to_table(ptr, fn); - rgb[i].fOffset = offset; - rgb[i].fCount = kDefaultTableSize; - offset += kDefaultTableSize * sizeof(float); - ptr += kDefaultTableSize; - } - - tables->fRed = rgb[0]; - tables->fGreen = rgb[1]; - tables->fBlue = rgb[2]; - return true; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// - static constexpr char kDescriptionTagBodyPrefix[12] = { 'G', 'o', 'o', 'g', 'l', 'e', '/', 'S', 'k', 'i', 'a' , '/'}; @@ -165,9 +44,14 @@ static constexpr uint32_t kWhitePointTag[5] { // Google Inc. 2016 (UTF-16) static constexpr uint8_t kCopyrightTagBody[] = { - 0x00, 0x47, 0x00, 0x6f, 0x00, 0x6f, 0x00, 0x67, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x20, 0x00, - 0x49, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x2e, 0x00, 0x20, 0x00, 0x32, 0x00, 0x30, 0x00, 0x31, - 0x00, 0x36, + 0x00, 0x47, 0x00, 0x6f, + 0x00, 0x6f, 0x00, 0x67, + 0x00, 0x6c, 0x00, 0x65, + 0x00, 0x20, 0x00, 0x49, + 0x00, 0x6e, 0x00, 0x63, + 0x00, 0x2e, 0x00, 0x20, + 0x00, 0x32, 0x00, 0x30, + 0x00, 0x31, 0x00, 0x36, }; static_assert(SkIsAlign4(sizeof(kCopyrightTagBody)), "Copyright must be aligned to 4-bytes."); static constexpr uint32_t kCopyrightTagHeader[7] { @@ -288,12 +172,12 @@ static SkFixed float_round_to_fixed(float x) { return sk_float_saturate2int((float)floor((double)x * SK_Fixed1 + 0.5)); } -static void write_xyz_tag(uint32_t* ptr, const SkMatrix44& toXYZ, int col) { +static void write_xyz_tag(uint32_t* ptr, const float toXYZD50[9], int col) { ptr[0] = SkEndian_SwapBE32(kXYZ_PCSSpace); ptr[1] = 0; - ptr[2] = SkEndian_SwapBE32(float_round_to_fixed(toXYZ.getFloat(0, col))); - ptr[3] = SkEndian_SwapBE32(float_round_to_fixed(toXYZ.getFloat(1, col))); - ptr[4] = SkEndian_SwapBE32(float_round_to_fixed(toXYZ.getFloat(2, col))); + ptr[2] = SkEndian_SwapBE32(float_round_to_fixed(toXYZD50[0*3 + col])); + ptr[3] = SkEndian_SwapBE32(float_round_to_fixed(toXYZD50[1*3 + col])); + ptr[4] = SkEndian_SwapBE32(float_round_to_fixed(toXYZD50[2*3 + col])); } static void write_trc_tag(uint32_t* ptr, const SkColorSpaceTransferFn& fn) { @@ -309,12 +193,6 @@ static void write_trc_tag(uint32_t* ptr, const SkColorSpaceTransferFn& fn) { ptr[9] = SkEndian_SwapBE32(float_round_to_fixed(fn.fF)); } -static bool is_3x3(const SkMatrix44& toXYZD50) { - return 0.0f == toXYZD50.get(3, 0) && 0.0f == toXYZD50.get(3, 1) && 0.0f == toXYZD50.get(3, 2) && - 0.0f == toXYZD50.get(0, 3) && 0.0f == toXYZD50.get(1, 3) && 0.0f == toXYZD50.get(2, 3) && - 1.0f == toXYZD50.get(3, 3); -} - static bool nearly_equal(float x, float y) { // A note on why I chose this tolerance: transfer_fn_almost_equal() uses a // tolerance of 0.001f, which doesn't seem to be enough to distinguish @@ -338,28 +216,18 @@ static bool nearly_equal(const SkColorSpaceTransferFn& u, && nearly_equal(u.fF, v.fF); } -static bool nearly_equal(const SkMatrix44& toXYZD50, const float standard[9]) { - return nearly_equal(toXYZD50.getFloat(0, 0), standard[0]) - && nearly_equal(toXYZD50.getFloat(0, 1), standard[1]) - && nearly_equal(toXYZD50.getFloat(0, 2), standard[2]) - && nearly_equal(toXYZD50.getFloat(1, 0), standard[3]) - && nearly_equal(toXYZD50.getFloat(1, 1), standard[4]) - && nearly_equal(toXYZD50.getFloat(1, 2), standard[5]) - && nearly_equal(toXYZD50.getFloat(2, 0), standard[6]) - && nearly_equal(toXYZD50.getFloat(2, 1), standard[7]) - && nearly_equal(toXYZD50.getFloat(2, 2), standard[8]) - && nearly_equal(toXYZD50.getFloat(0, 3), 0.0f) - && nearly_equal(toXYZD50.getFloat(1, 3), 0.0f) - && nearly_equal(toXYZD50.getFloat(2, 3), 0.0f) - && nearly_equal(toXYZD50.getFloat(3, 0), 0.0f) - && nearly_equal(toXYZD50.getFloat(3, 1), 0.0f) - && nearly_equal(toXYZD50.getFloat(3, 2), 0.0f) - && nearly_equal(toXYZD50.getFloat(3, 3), 1.0f); +static bool nearly_equal(const float u[9], const float v[9]) { + for (int i = 0; i < 9; i++) { + if (!nearly_equal(u[i], v[i])) { + return false; + } + } + return true; } // Return nullptr if the color profile doen't have a special name. const char* get_color_profile_description(const SkColorSpaceTransferFn& fn, - const SkMatrix44& toXYZD50) { + const float toXYZD50[9]) { bool srgb_xfer = nearly_equal(fn, gSRGB_TransferFn); bool srgb_gamut = nearly_equal(toXYZD50, gSRGB_toXYZD50); if (srgb_xfer && srgb_gamut) { @@ -400,7 +268,7 @@ const char* get_color_profile_description(const SkColorSpaceTransferFn& fn, static void get_color_profile_tag(char dst[kICCDescriptionTagSize], const SkColorSpaceTransferFn& fn, - const SkMatrix44& toXYZD50) { + const float toXYZD50[9]) { SkASSERT(dst); if (const char* description = get_color_profile_description(fn, toXYZD50)) { SkASSERT(strlen(description) < kICCDescriptionTagSize); @@ -410,12 +278,7 @@ static void get_color_profile_tag(char dst[kICCDescriptionTagSize], } else { strncpy(dst, kDescriptionTagBodyPrefix, sizeof(kDescriptionTagBodyPrefix)); SkMD5 md5; - for (int i = 0; i < 3; ++i) { - for (int j = 0; j < 3; ++j) { - float value = toXYZD50.getFloat(i,j); - md5.write(&value, sizeof(value)); - } - } + md5.write(toXYZD50, 9*sizeof(float)); static_assert(sizeof(fn) == sizeof(float) * 7, "packed"); md5.write(&fn, sizeof(fn)); SkMD5::Digest digest; @@ -430,29 +293,8 @@ static void get_color_profile_tag(char dst[kICCDescriptionTagSize], } } -SkString SkICCGetColorProfileTag(const SkColorSpaceTransferFn& fn, - const SkMatrix44& toXYZD50) { - char tag[kICCDescriptionTagSize]; - get_color_profile_tag(tag, fn, toXYZD50); - size_t len = kICCDescriptionTagSize; - while (len > 0 && tag[len - 1] == '\0') { - --len; // tag is padded out with zeros - } - SkASSERT(len != 0); - return SkString(tag, len); -} - -// returns pointer just beyond where we just wrote. -static uint8_t* string_copy_ascii_to_utf16be(uint8_t* dst, const char* src, size_t count) { - while (count-- > 0) { - *dst++ = 0; - *dst++ = (uint8_t)(*src++); - } - return dst; -} - -sk_sp<SkData> SkICC::WriteToICC(const SkColorSpaceTransferFn& fn, const SkMatrix44& toXYZD50) { - if (!is_3x3(toXYZD50) || !is_valid_transfer_fn(fn)) { +sk_sp<SkData> SkWriteICCProfile(const SkColorSpaceTransferFn& fn, const float toXYZD50[9]) { + if (!is_valid_transfer_fn(fn)) { return nullptr; } @@ -473,7 +315,12 @@ sk_sp<SkData> SkICC::WriteToICC(const SkColorSpaceTransferFn& fn, const SkMatrix { char colorProfileTag[kICCDescriptionTagSize]; get_color_profile_tag(colorProfileTag, fn, toXYZD50); - ptr = string_copy_ascii_to_utf16be(ptr, colorProfileTag, kICCDescriptionTagSize); + + // ASCII --> big-endian UTF-16. + for (size_t i = 0; i < kICCDescriptionTagSize; i++) { + *ptr++ = 0; + *ptr++ = colorProfileTag[i]; + } } // Write XYZ tags diff --git a/src/core/SkICCPriv.h b/src/core/SkICCPriv.h index a50d362a55..3d2b8965a9 100644 --- a/src/core/SkICCPriv.h +++ b/src/core/SkICCPriv.h @@ -51,11 +51,4 @@ enum ParaCurveType { kGABCDEF_ParaCurveType = 4, }; -/* - * Given fn and toXYZD50, generate a decription tag that either includes a hash - * of the function and gamut or is a special name. - * Exposed for unit testing and tools. - */ -SkString SkICCGetColorProfileTag(const SkColorSpaceTransferFn& fn, - const SkMatrix44& toXYZD50); #endif // SkICCPriv_DEFINED diff --git a/src/images/SkImageEncoderFns.h b/src/images/SkImageEncoderFns.h index 8637541720..d8d1c64bb8 100644 --- a/src/images/SkImageEncoderFns.h +++ b/src/images/SkImageEncoderFns.h @@ -427,8 +427,6 @@ static inline sk_sp<SkData> icc_from_color_space(const SkImageInfo& info) { if (cs->isNumericalTransferFn(&fn) && cs->toXYZD50(&toXYZD50)) { return SkICC::WriteToICC(fn, toXYZD50); } - - // TODO: Should we support writing ICC profiles for additional color spaces? return nullptr; } |