Index: src/core/SkColorSpace_ICC.cpp |
diff --git a/src/core/SkColorSpace.cpp b/src/core/SkColorSpace_ICC.cpp |
similarity index 79% |
copy from src/core/SkColorSpace.cpp |
copy to src/core/SkColorSpace_ICC.cpp |
index f988c7d3232e3468a2cb6831be9ecdb285c327db..e4be8f4e4e6c92623cd31ef076d9f210dc70e048 100644 |
--- a/src/core/SkColorSpace.cpp |
+++ b/src/core/SkColorSpace_ICC.cpp |
@@ -7,163 +7,8 @@ |
#include "SkColorSpace.h" |
#include "SkColorSpace_Base.h" |
+#include "SkColorSpacePriv.h" |
#include "SkEndian.h" |
-#include "SkOnce.h" |
-#include "SkReadBuffer.h" |
-#include "SkWriteBuffer.h" |
- |
-#define SkColorSpacePrintf(...) |
- |
-static bool color_space_almost_equal(float a, float b) { |
- return SkTAbs(a - b) < 0.01f; |
-} |
- |
-////////////////////////////////////////////////////////////////////////////////////////////////// |
- |
-SkColorSpace::SkColorSpace(GammaNamed gammaNamed, const SkMatrix44& toXYZD50, Named named) |
- : fGammaNamed(gammaNamed) |
- , fToXYZD50(toXYZD50) |
- , fNamed(named) |
-{} |
- |
-SkColorSpace_Base::SkColorSpace_Base(GammaNamed gammaNamed, const SkMatrix44& toXYZD50, Named named) |
- : INHERITED(gammaNamed, toXYZD50, named) |
- , fGammas(nullptr) |
- , fProfileData(nullptr) |
-{} |
- |
-SkColorSpace_Base::SkColorSpace_Base(sk_sp<SkColorLookUpTable> colorLUT, sk_sp<SkGammas> gammas, |
- const SkMatrix44& toXYZD50, sk_sp<SkData> profileData) |
- : INHERITED(kNonStandard_GammaNamed, toXYZD50, kUnknown_Named) |
- , fColorLUT(std::move(colorLUT)) |
- , fGammas(std::move(gammas)) |
- , fProfileData(std::move(profileData)) |
-{} |
- |
-static constexpr float gSRGB_toXYZD50[] { |
- 0.4358f, 0.2224f, 0.0139f, // * R |
- 0.3853f, 0.7170f, 0.0971f, // * G |
- 0.1430f, 0.0606f, 0.7139f, // * B |
-}; |
- |
-static constexpr float gAdobeRGB_toXYZD50[] { |
- 0.6098f, 0.3111f, 0.0195f, // * R |
- 0.2052f, 0.6257f, 0.0609f, // * G |
- 0.1492f, 0.0632f, 0.7448f, // * B |
-}; |
- |
-/** |
- * Checks if our toXYZ matrix is a close match to a known color gamut. |
- * |
- * @param toXYZD50 transformation matrix deduced from profile data |
- * @param standard 3x3 canonical transformation matrix |
- */ |
-static bool xyz_almost_equal(const SkMatrix44& toXYZD50, const float* standard) { |
- return color_space_almost_equal(toXYZD50.getFloat(0, 0), standard[0]) && |
- color_space_almost_equal(toXYZD50.getFloat(0, 1), standard[1]) && |
- color_space_almost_equal(toXYZD50.getFloat(0, 2), standard[2]) && |
- color_space_almost_equal(toXYZD50.getFloat(1, 0), standard[3]) && |
- color_space_almost_equal(toXYZD50.getFloat(1, 1), standard[4]) && |
- color_space_almost_equal(toXYZD50.getFloat(1, 2), standard[5]) && |
- color_space_almost_equal(toXYZD50.getFloat(2, 0), standard[6]) && |
- color_space_almost_equal(toXYZD50.getFloat(2, 1), standard[7]) && |
- color_space_almost_equal(toXYZD50.getFloat(2, 2), standard[8]) && |
- color_space_almost_equal(toXYZD50.getFloat(0, 3), 0.0f) && |
- color_space_almost_equal(toXYZD50.getFloat(1, 3), 0.0f) && |
- color_space_almost_equal(toXYZD50.getFloat(2, 3), 0.0f) && |
- color_space_almost_equal(toXYZD50.getFloat(3, 0), 0.0f) && |
- color_space_almost_equal(toXYZD50.getFloat(3, 1), 0.0f) && |
- color_space_almost_equal(toXYZD50.getFloat(3, 2), 0.0f) && |
- color_space_almost_equal(toXYZD50.getFloat(3, 3), 1.0f); |
-} |
- |
-static void set_gamma_value(SkGammaCurve* gamma, float value) { |
- if (color_space_almost_equal(2.2f, value)) { |
- gamma->fNamed = SkColorSpace::k2Dot2Curve_GammaNamed; |
- } else if (color_space_almost_equal(1.0f, value)) { |
- gamma->fNamed = SkColorSpace::kLinear_GammaNamed; |
- } else if (color_space_almost_equal(0.0f, value)) { |
- SkColorSpacePrintf("Treating invalid zero gamma as linear."); |
- gamma->fNamed = SkColorSpace::kLinear_GammaNamed; |
- } else { |
- gamma->fValue = value; |
- } |
-} |
- |
-sk_sp<SkColorSpace> SkColorSpace_Base::NewRGB(float values[3], const SkMatrix44& toXYZD50) { |
- SkGammaCurve curves[3]; |
- set_gamma_value(&curves[0], values[0]); |
- set_gamma_value(&curves[1], values[1]); |
- set_gamma_value(&curves[2], values[2]); |
- |
- GammaNamed gammaNamed = SkGammas::Named(curves); |
- if (kNonStandard_GammaNamed == gammaNamed) { |
- sk_sp<SkGammas> gammas(new SkGammas(std::move(curves[0]), std::move(curves[1]), |
- std::move(curves[2]))); |
- return sk_sp<SkColorSpace>(new SkColorSpace_Base(nullptr, gammas, toXYZD50, nullptr)); |
- } |
- |
- return SkColorSpace_Base::NewRGB(gammaNamed, toXYZD50); |
-} |
- |
-sk_sp<SkColorSpace> SkColorSpace_Base::NewRGB(GammaNamed gammaNamed, const SkMatrix44& toXYZD50) { |
- switch (gammaNamed) { |
- case kSRGB_GammaNamed: |
- if (xyz_almost_equal(toXYZD50, gSRGB_toXYZD50)) { |
- return SkColorSpace::NewNamed(kSRGB_Named); |
- } |
- break; |
- case k2Dot2Curve_GammaNamed: |
- if (xyz_almost_equal(toXYZD50, gAdobeRGB_toXYZD50)) { |
- return SkColorSpace::NewNamed(kAdobeRGB_Named); |
- } |
- break; |
- case kNonStandard_GammaNamed: |
- // This is not allowed. |
- return nullptr; |
- default: |
- break; |
- } |
- |
- return sk_sp<SkColorSpace>(new SkColorSpace_Base(gammaNamed, toXYZD50, kUnknown_Named)); |
-} |
- |
-sk_sp<SkColorSpace> SkColorSpace::NewRGB(GammaNamed gammaNamed, const SkMatrix44& toXYZD50) { |
- return SkColorSpace_Base::NewRGB(gammaNamed, toXYZD50); |
-} |
- |
-sk_sp<SkColorSpace> SkColorSpace::NewNamed(Named named) { |
- static SkOnce sRGBOnce; |
- static SkColorSpace* sRGB; |
- static SkOnce adobeRGBOnce; |
- static SkColorSpace* adobeRGB; |
- |
- switch (named) { |
- case kSRGB_Named: { |
- sRGBOnce([] { |
- SkMatrix44 srgbToxyzD50(SkMatrix44::kUninitialized_Constructor); |
- srgbToxyzD50.set3x3RowMajorf(gSRGB_toXYZD50); |
- sRGB = new SkColorSpace_Base(kSRGB_GammaNamed, srgbToxyzD50, kSRGB_Named); |
- }); |
- return sk_ref_sp(sRGB); |
- } |
- case kAdobeRGB_Named: { |
- adobeRGBOnce([] { |
- SkMatrix44 adobergbToxyzD50(SkMatrix44::kUninitialized_Constructor); |
- adobergbToxyzD50.set3x3RowMajorf(gAdobeRGB_toXYZD50); |
- adobeRGB = new SkColorSpace_Base(k2Dot2Curve_GammaNamed, adobergbToxyzD50, |
- kAdobeRGB_Named); |
- }); |
- return sk_ref_sp(adobeRGB); |
- } |
- default: |
- break; |
- } |
- return nullptr; |
-} |
- |
-/////////////////////////////////////////////////////////////////////////////////////////////////// |
- |
#include "SkFixed.h" |
#include "SkTemplates.h" |
@@ -1207,153 +1052,3 @@ sk_sp<SkData> SkColorSpace_Base::writeToICC() const { |
// the client calls again? |
return SkData::MakeFromMalloc(profile.release(), kICCProfileSize); |
} |
- |
-/////////////////////////////////////////////////////////////////////////////////////////////////// |
- |
-enum Version { |
- k0_Version, // Initial version, header + flags for matrix and profile |
-}; |
- |
-struct ColorSpaceHeader { |
- /** |
- * If kMatrix_Flag is set, we will write 12 floats after the header. |
- * Should not be set at the same time as the kICC_Flag. |
- */ |
- static constexpr uint8_t kMatrix_Flag = 1 << 0; |
- |
- /** |
- * If kICC_Flag is set, we will write an ICC profile after the header. |
- * The ICC profile will be written as a uint32 size, followed immediately |
- * by the data (padded to 4 bytes). |
- * Should not be set at the same time as the kMatrix_Flag. |
- */ |
- static constexpr uint8_t kICC_Flag = 1 << 1; |
- |
- static ColorSpaceHeader Pack(Version version, SkColorSpace::Named named, |
- SkColorSpace::GammaNamed gammaNamed, uint8_t flags) { |
- ColorSpaceHeader header; |
- |
- SkASSERT(k0_Version == version); |
- header.fVersion = (uint8_t) version; |
- |
- SkASSERT(named <= SkColorSpace::kAdobeRGB_Named); |
- header.fNamed = (uint8_t) named; |
- |
- SkASSERT(gammaNamed <= SkColorSpace::kNonStandard_GammaNamed); |
- header.fGammaNamed = (uint8_t) gammaNamed; |
- |
- SkASSERT(flags <= kICC_Flag); |
- header.fFlags = flags; |
- return header; |
- } |
- |
- uint8_t fVersion; // Always zero |
- uint8_t fNamed; // Must be a SkColorSpace::Named |
- uint8_t fGammaNamed; // Must be a SkColorSpace::GammaNamed |
- uint8_t fFlags; // Some combination of the flags listed above |
-}; |
- |
-sk_sp<SkData> SkColorSpace::serialize() const { |
- // If we have a named profile, only write the enum. |
- switch (fNamed) { |
- case kSRGB_Named: |
- case kAdobeRGB_Named: { |
- sk_sp<SkData> data = SkData::MakeUninitialized(sizeof(ColorSpaceHeader)); |
- *((ColorSpaceHeader*) data->writable_data()) = |
- ColorSpaceHeader::Pack(k0_Version, fNamed, fGammaNamed, 0); |
- return data; |
- } |
- default: |
- break; |
- } |
- |
- // If we have a named gamma, write the enum and the matrix. |
- switch (fGammaNamed) { |
- case kSRGB_GammaNamed: |
- case k2Dot2Curve_GammaNamed: |
- case kLinear_GammaNamed: { |
- sk_sp<SkData> data = SkData::MakeUninitialized(sizeof(ColorSpaceHeader) + |
- 12 * sizeof(float)); |
- void* dataPtr = data->writable_data(); |
- |
- *((ColorSpaceHeader*) dataPtr) = ColorSpaceHeader::Pack(k0_Version, fNamed, fGammaNamed, |
- ColorSpaceHeader::kMatrix_Flag); |
- dataPtr = SkTAddOffset<void>(dataPtr, sizeof(ColorSpaceHeader)); |
- |
- fToXYZD50.as4x3ColMajorf((float*) dataPtr); |
- return data; |
- } |
- default: |
- break; |
- } |
- |
- // If we do not have a named gamma, this must have been created from an ICC profile. |
- // Since we were unable to recognize the gamma, we will have saved the ICC data. |
- SkASSERT(as_CSB(this)->fProfileData); |
- |
- size_t profileSize = as_CSB(this)->fProfileData->size(); |
- if (SkAlign4(profileSize) != (uint32_t) SkAlign4(profileSize)) { |
- return nullptr; |
- } |
- |
- sk_sp<SkData> data = SkData::MakeUninitialized(sizeof(ColorSpaceHeader) + sizeof(uint32_t) + |
- SkAlign4(profileSize)); |
- void* dataPtr = data->writable_data(); |
- |
- *((ColorSpaceHeader*) dataPtr) = ColorSpaceHeader::Pack(k0_Version, fNamed, fGammaNamed, |
- ColorSpaceHeader::kICC_Flag); |
- dataPtr = SkTAddOffset<void>(dataPtr, sizeof(ColorSpaceHeader)); |
- |
- *((uint32_t*) dataPtr) = (uint32_t) SkAlign4(profileSize); |
- dataPtr = SkTAddOffset<void>(dataPtr, sizeof(uint32_t)); |
- |
- memcpy(dataPtr, as_CSB(this)->fProfileData->data(), profileSize); |
- memset(SkTAddOffset<void>(dataPtr, profileSize), 0, SkAlign4(profileSize) - profileSize); |
- return data; |
-} |
- |
-sk_sp<SkColorSpace> SkColorSpace::Deserialize(const void* data, size_t length) { |
- if (length < sizeof(ColorSpaceHeader)) { |
- return nullptr; |
- } |
- |
- ColorSpaceHeader header = *((const ColorSpaceHeader*) data); |
- data = SkTAddOffset<const void>(data, sizeof(ColorSpaceHeader)); |
- length -= sizeof(ColorSpaceHeader); |
- switch ((Named) header.fNamed) { |
- case kSRGB_Named: |
- case kAdobeRGB_Named: |
- return NewNamed((Named) header.fNamed); |
- default: |
- break; |
- } |
- |
- switch ((GammaNamed) header.fGammaNamed) { |
- case kSRGB_GammaNamed: |
- case k2Dot2Curve_GammaNamed: |
- case kLinear_GammaNamed: { |
- if (ColorSpaceHeader::kMatrix_Flag != header.fFlags || length < 12 * sizeof(float)) { |
- return nullptr; |
- } |
- |
- SkMatrix44 toXYZ(SkMatrix44::kUninitialized_Constructor); |
- toXYZ.set4x3ColMajorf((const float*) data); |
- return NewRGB((GammaNamed) header.fGammaNamed, toXYZ); |
- } |
- default: |
- break; |
- } |
- |
- if (ColorSpaceHeader::kICC_Flag != header.fFlags || length < sizeof(uint32_t)) { |
- return nullptr; |
- } |
- |
- uint32_t profileSize = *((uint32_t*) data); |
- data = SkTAddOffset<const void>(data, sizeof(uint32_t)); |
- length -= sizeof(uint32_t); |
- if (length < profileSize) { |
- return nullptr; |
- } |
- |
- return NewICC(data, profileSize); |
-} |