Add SkColorSpace::Equals() API
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2196743002
Review-Url: https://codereview.chromium.org/2196743002
diff --git a/include/core/SkColorSpace.h b/include/core/SkColorSpace.h
index 9fc5ccd..4b373f4 100644
--- a/include/core/SkColorSpace.h
+++ b/include/core/SkColorSpace.h
@@ -104,6 +104,12 @@
static sk_sp<SkColorSpace> Deserialize(const void* data, size_t length);
+ /**
+ * If both are null, we return true. If one is null and the other is not, we return false.
+ * If both are non-null, we do a deeper compare.
+ */
+ static bool Equals(const SkColorSpace* src, const SkColorSpace* dst);
+
protected:
SkColorSpace(GammaNamed gammaNamed, const SkMatrix44& toXYZD50, Named named);
diff --git a/include/core/SkImageInfo.h b/include/core/SkImageInfo.h
index f143503..cf50aca 100644
--- a/include/core/SkImageInfo.h
+++ b/include/core/SkImageInfo.h
@@ -289,12 +289,10 @@
bool operator==(const SkImageInfo& other) const {
return fWidth == other.fWidth && fHeight == other.fHeight &&
fColorType == other.fColorType && fAlphaType == other.fAlphaType &&
- fColorSpace == other.fColorSpace;
+ SkColorSpace::Equals(fColorSpace.get(), other.fColorSpace.get());
}
bool operator!=(const SkImageInfo& other) const {
- return fWidth != other.fWidth || fHeight != other.fHeight ||
- fColorType != other.fColorType || fAlphaType != other.fAlphaType ||
- fColorSpace != other.fColorSpace;
+ return !(*this == other);
}
void unflatten(SkReadBuffer&);
diff --git a/src/codec/SkJpegCodec.cpp b/src/codec/SkJpegCodec.cpp
index d158b42..2eea46b 100644
--- a/src/codec/SkJpegCodec.cpp
+++ b/src/codec/SkJpegCodec.cpp
@@ -475,10 +475,9 @@
}
static bool needs_color_xform(const SkImageInfo& dstInfo, const SkImageInfo& srcInfo) {
- // FIXME (msarett):
- // Do a better check for color space equality.
return (kRGBA_F16_SkColorType == dstInfo.colorType()) ||
- (dstInfo.colorSpace() && (dstInfo.colorSpace() != srcInfo.colorSpace()));
+ (dstInfo.colorSpace() && !SkColorSpace::Equals(srcInfo.colorSpace(),
+ dstInfo.colorSpace()));
}
int SkJpegCodec::readRows(const SkImageInfo& dstInfo, void* dst, size_t rowBytes, int count) {
diff --git a/src/core/SkColorSpace.cpp b/src/core/SkColorSpace.cpp
index 3874f0e..e7bd4e8 100644
--- a/src/core/SkColorSpace.cpp
+++ b/src/core/SkColorSpace.cpp
@@ -316,6 +316,51 @@
return NewICC(data, profileSize);
}
+bool SkColorSpace::Equals(const SkColorSpace* src, const SkColorSpace* dst) {
+ if (src == dst) {
+ return true;
+ }
+
+ if (!src || !dst) {
+ return false;
+ }
+
+ switch (src->fNamed) {
+ case kSRGB_Named:
+ case kAdobeRGB_Named:
+ return src->fNamed == dst->fNamed;
+ case kUnknown_Named:
+ if (kUnknown_Named != dst->fNamed) {
+ return false;
+ }
+ break;
+ }
+
+ SkData* srcData = as_CSB(src)->fProfileData.get();
+ SkData* dstData = as_CSB(dst)->fProfileData.get();
+ if (srcData || dstData) {
+ if (srcData && dstData) {
+ return srcData->size() == dstData->size() &&
+ 0 == memcmp(srcData->data(), dstData->data(), srcData->size());
+ }
+
+ return false;
+ }
+
+ // It's important to check fProfileData before named gammas. Some profiles may have named
+ // gammas, but also include other wacky features that cause us to save the data.
+ switch (src->fGammaNamed) {
+ case kSRGB_GammaNamed:
+ case k2Dot2Curve_GammaNamed:
+ case kLinear_GammaNamed:
+ return (src->fGammaNamed == dst->fGammaNamed) && (src->fToXYZD50 == dst->fToXYZD50);
+ default:
+ // If |src| does not have a named gamma, fProfileData should be non-null.
+ SkASSERT(false);
+ return false;
+ }
+}
+
bool SkColorSpace::gammasAreMatching() const {
const SkGammas* gammas = as_CSB(this)->gammas();
SkASSERT(gammas);
diff --git a/tests/ColorSpaceTest.cpp b/tests/ColorSpaceTest.cpp
index 62a898c..8837c38 100644
--- a/tests/ColorSpaceTest.cpp
+++ b/tests/ColorSpaceTest.cpp
@@ -221,3 +221,34 @@
test_serialize(r, SkColorSpace::NewICC(monitorData->data(), monitorData->size()).get(), false);
}
+DEF_TEST(ColorSpace_Equals, r) {
+ sk_sp<SkColorSpace> srgb = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named);
+ sk_sp<SkColorSpace> adobe = SkColorSpace::NewNamed(SkColorSpace::kAdobeRGB_Named);
+ sk_sp<SkData> data = SkData::MakeFromFileName(
+ GetResourcePath("icc_profiles/HP_ZR30w.icc").c_str());
+ sk_sp<SkColorSpace> z30 = SkColorSpace::NewICC(data->data(), data->size());
+ data = SkData::MakeFromFileName( GetResourcePath("icc_profiles/HP_Z32x.icc").c_str());
+ sk_sp<SkColorSpace> z32 = SkColorSpace::NewICC(data->data(), data->size());
+ data = SkData::MakeFromFileName(GetResourcePath("icc_profiles/upperLeft.icc").c_str());
+ sk_sp<SkColorSpace> upperLeft = SkColorSpace::NewICC(data->data(), data->size());
+ data = SkData::MakeFromFileName(GetResourcePath("icc_profiles/upperRight.icc").c_str());
+ sk_sp<SkColorSpace> upperRight = SkColorSpace::NewICC(data->data(), data->size());
+
+ REPORTER_ASSERT(r, SkColorSpace::Equals(nullptr, nullptr));
+ REPORTER_ASSERT(r, SkColorSpace::Equals(srgb.get(), srgb.get()));
+ REPORTER_ASSERT(r, SkColorSpace::Equals(adobe.get(), adobe.get()));
+ REPORTER_ASSERT(r, SkColorSpace::Equals(z30.get(), z30.get()));
+ REPORTER_ASSERT(r, SkColorSpace::Equals(z32.get(), z32.get()));
+ REPORTER_ASSERT(r, SkColorSpace::Equals(upperLeft.get(), upperLeft.get()));
+ REPORTER_ASSERT(r, SkColorSpace::Equals(upperRight.get(), upperRight.get()));
+
+ REPORTER_ASSERT(r, !SkColorSpace::Equals(nullptr, srgb.get()));
+ REPORTER_ASSERT(r, !SkColorSpace::Equals(srgb.get(), nullptr));
+ REPORTER_ASSERT(r, !SkColorSpace::Equals(adobe.get(), srgb.get()));
+ REPORTER_ASSERT(r, !SkColorSpace::Equals(z30.get(), srgb.get()));
+ REPORTER_ASSERT(r, !SkColorSpace::Equals(z32.get(), z30.get()));
+ REPORTER_ASSERT(r, !SkColorSpace::Equals(upperLeft.get(), srgb.get()));
+ REPORTER_ASSERT(r, !SkColorSpace::Equals(upperLeft.get(), upperRight.get()));
+ REPORTER_ASSERT(r, !SkColorSpace::Equals(z30.get(), upperRight.get()));
+ REPORTER_ASSERT(r, !SkColorSpace::Equals(upperRight.get(), adobe.get()));
+}
diff --git a/tests/ImageIsOpaqueTest.cpp b/tests/ImageIsOpaqueTest.cpp
index 0660885..4389a3d 100644
--- a/tests/ImageIsOpaqueTest.cpp
+++ b/tests/ImageIsOpaqueTest.cpp
@@ -6,6 +6,7 @@
*/
#include "SkTypes.h"
+#include "Resources.h"
#include "Test.h"
#if SK_SUPPORT_GPU
@@ -17,13 +18,15 @@
#include "SkWriteBuffer.h"
static void test_flatten(skiatest::Reporter* reporter, const SkImageInfo& info) {
- // just need a safe amount of storage, but ensure that it is 4-byte aligned.
- int32_t storage[(sizeof(SkImageInfo)*2) / sizeof(int32_t)];
- SkBinaryWriteBuffer wb(storage, sizeof(storage));
+ // Need a safe amount of 4-byte aligned storage. Note that one of the test ICC profiles
+ // is ~7500 bytes.
+ const size_t storageBytes = 8000;
+ SkAutoTMalloc<uint32_t> storage(storageBytes / sizeof(uint32_t));
+ SkBinaryWriteBuffer wb(storage.get(), storageBytes);
info.flatten(wb);
- SkASSERT(wb.bytesWritten() < sizeof(storage));
+ SkASSERT(wb.bytesWritten() < storageBytes);
- SkReadBuffer rb(storage, wb.bytesWritten());
+ SkReadBuffer rb(storage.get(), wb.bytesWritten());
// pick a noisy byte pattern, so we ensure that unflatten sets all of our fields
SkImageInfo info2 = SkImageInfo::Make(0xB8, 0xB8, (SkColorType) 0xB8, (SkAlphaType) 0xB8);
@@ -35,10 +38,24 @@
}
DEF_TEST(ImageInfo_flattening, reporter) {
+ sk_sp<SkData> data =
+ SkData::MakeFromFileName(GetResourcePath("icc_profiles/HP_ZR30w.icc").c_str());
+ sk_sp<SkColorSpace> space0 = SkColorSpace::NewICC(data->data(), data->size());
+ data = SkData::MakeFromFileName( GetResourcePath("icc_profiles/HP_Z32x.icc").c_str());
+ sk_sp<SkColorSpace> space1 = SkColorSpace::NewICC(data->data(), data->size());
+ data = SkData::MakeFromFileName(GetResourcePath("icc_profiles/upperLeft.icc").c_str());
+ sk_sp<SkColorSpace> space2 = SkColorSpace::NewICC(data->data(), data->size());
+ data = SkData::MakeFromFileName(GetResourcePath("icc_profiles/upperRight.icc").c_str());
+ sk_sp<SkColorSpace> space3 = SkColorSpace::NewICC(data->data(), data->size());
+
sk_sp<SkColorSpace> spaces[] = {
nullptr,
SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named),
SkColorSpace::NewNamed(SkColorSpace::kAdobeRGB_Named),
+ space0,
+ space1,
+ space2,
+ space3,
};
for (int ct = 0; ct <= kLastEnum_SkColorType; ++ct) {