Hash the gamut of XYZ color spaces, to speed up comparison
Also going to use this to allow caching of GrColorSpaceXforms BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=3670 Change-Id: I56ed2dcbdddc22046263f56d68f2d6aea55547c8 Reviewed-on: https://skia-review.googlesource.com/3670 Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: Matt Sarett <msarett@google.com> Reviewed-by: Brian Salomon <bsalomon@google.com>
This commit is contained in:
parent
8ffb26051f
commit
bbf251bf22
@ -576,16 +576,20 @@ bool SkColorSpace::Equals(const SkColorSpace* src, const SkColorSpace* dst) {
|
||||
const SkColorSpace_XYZ* srcXYZ = static_cast<const SkColorSpace_XYZ*>(src);
|
||||
const SkColorSpace_XYZ* dstXYZ = static_cast<const SkColorSpace_XYZ*>(dst);
|
||||
|
||||
if (srcXYZ->gammaNamed() != dstXYZ->gammaNamed()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (srcXYZ->gammaNamed()) {
|
||||
case kSRGB_SkGammaNamed:
|
||||
case k2Dot2Curve_SkGammaNamed:
|
||||
case kLinear_SkGammaNamed:
|
||||
return (srcXYZ->gammaNamed() == dstXYZ->gammaNamed()) &&
|
||||
(*srcXYZ->toXYZD50() == *dstXYZ->toXYZD50());
|
||||
default:
|
||||
if (srcXYZ->gammaNamed() != dstXYZ->gammaNamed()) {
|
||||
return false;
|
||||
if (srcXYZ->toXYZD50Hash() == dstXYZ->toXYZD50Hash()) {
|
||||
SkASSERT(*srcXYZ->toXYZD50() == *dstXYZ->toXYZD50() && "Hash collision");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
default:
|
||||
// It is unlikely that we will reach this case.
|
||||
sk_sp<SkData> serializedSrcData = src->serialize();
|
||||
sk_sp<SkData> serializedDstData = dst->serialize();
|
||||
|
@ -337,20 +337,6 @@ void SkColorSpaceXform_Base::BuildDstGammaTables(const uint8_t* dstGammaTables[3
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static inline bool is_almost_identity(const SkMatrix44& srcToDst) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int j = 0; j < 4; j++) {
|
||||
float expected = (i == j) ? 1.0f : 0.0f;
|
||||
if (!color_space_almost_equal(srcToDst.getFloat(i,j), expected)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::unique_ptr<SkColorSpaceXform> SkColorSpaceXform::New(SkColorSpace* srcSpace,
|
||||
SkColorSpace* dstSpace) {
|
||||
if (!srcSpace || !dstSpace) {
|
||||
@ -381,11 +367,12 @@ std::unique_ptr<SkColorSpaceXform> SkColorSpaceXform::New(SkColorSpace* srcSpace
|
||||
srcToDst.setIdentity();
|
||||
csm = kFull_ColorSpaceMatch;
|
||||
} else {
|
||||
srcToDst.setConcat(*dstSpaceXYZ->fromXYZD50(), *srcSpaceXYZ->toXYZD50());
|
||||
|
||||
if (is_almost_identity(srcToDst)) {
|
||||
if (srcSpaceXYZ->toXYZD50Hash() == dstSpaceXYZ->toXYZD50Hash()) {
|
||||
SkASSERT(*srcSpaceXYZ->toXYZD50() == *dstSpaceXYZ->toXYZD50() && "Hash collision");
|
||||
srcToDst.setIdentity();
|
||||
csm = kGamut_ColorSpaceMatch;
|
||||
} else {
|
||||
srcToDst.setConcat(*dstSpaceXYZ->fromXYZD50(), *srcSpaceXYZ->toXYZD50());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,11 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32_t toXYZD50Hash() const override {
|
||||
// See toXYZD50()'s comment.
|
||||
return 0;
|
||||
}
|
||||
|
||||
const SkMatrix44* fromXYZD50() const override {
|
||||
// See toXYZD50()'s comment. Also, A2B0 profiles are not supported
|
||||
// as destination color spaces, so an inverse matrix is never wanted.
|
||||
|
@ -176,6 +176,13 @@ public:
|
||||
*/
|
||||
virtual const SkMatrix44* toXYZD50() const = 0;
|
||||
|
||||
/**
|
||||
* Returns a hash of the gamut transofmration to XYZ D50. Allows for fast equality checking
|
||||
* of gamuts, at the (very small) risk of collision.
|
||||
* Returns 0 if color gamut cannot be described in terms of XYZ D50.
|
||||
*/
|
||||
virtual uint32_t toXYZD50Hash() const = 0;
|
||||
|
||||
/**
|
||||
* Describes color space gamut as a transformation from XYZ D50
|
||||
* Returns nullptr if color gamut cannot be described in terms of XYZ D50.
|
||||
|
@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
#include "SkColorSpace_XYZ.h"
|
||||
#include "SkChecksum.h"
|
||||
#include "SkColorSpaceXform_Base.h"
|
||||
|
||||
static constexpr float gSRGB_toXYZD50[] {
|
||||
@ -19,6 +20,7 @@ SkColorSpace_XYZ::SkColorSpace_XYZ(SkGammaNamed gammaNamed, const SkMatrix44& to
|
||||
, fGammaNamed(gammaNamed)
|
||||
, fGammas(nullptr)
|
||||
, fToXYZD50(toXYZD50)
|
||||
, fToXYZD50Hash(SkGoodHash()(toXYZD50))
|
||||
, fFromXYZD50(SkMatrix44::kUninitialized_Constructor)
|
||||
{}
|
||||
|
||||
@ -28,6 +30,7 @@ SkColorSpace_XYZ::SkColorSpace_XYZ(SkGammaNamed gammaNamed, sk_sp<SkGammas> gamm
|
||||
, fGammaNamed(gammaNamed)
|
||||
, fGammas(std::move(gammas))
|
||||
, fToXYZD50(toXYZD50)
|
||||
, fToXYZD50Hash(SkGoodHash()(toXYZD50))
|
||||
, fFromXYZD50(SkMatrix44::kUninitialized_Constructor)
|
||||
{}
|
||||
|
||||
|
@ -15,7 +15,8 @@
|
||||
class SkColorSpace_XYZ : public SkColorSpace_Base {
|
||||
public:
|
||||
const SkMatrix44* toXYZD50() const override { return &fToXYZD50; }
|
||||
|
||||
uint32_t toXYZD50Hash() const override { return fToXYZD50Hash; }
|
||||
|
||||
const SkMatrix44* fromXYZD50() const override;
|
||||
|
||||
bool onGammaCloseToSRGB() const override;
|
||||
@ -41,6 +42,7 @@ private:
|
||||
const SkGammaNamed fGammaNamed;
|
||||
sk_sp<SkGammas> fGammas;
|
||||
const SkMatrix44 fToXYZD50;
|
||||
uint32_t fToXYZD50Hash;
|
||||
|
||||
mutable SkMatrix44 fFromXYZD50;
|
||||
mutable SkOnce fFromXYZOnce;
|
||||
|
@ -10,31 +10,6 @@
|
||||
#include "SkColorSpace_Base.h"
|
||||
#include "SkMatrix44.h"
|
||||
|
||||
static inline bool sk_float_almost_equals(float x, float y, float tol) {
|
||||
return sk_float_abs(x - y) <= tol;
|
||||
}
|
||||
|
||||
static inline bool matrix_is_almost_identity(const SkMatrix44& m,
|
||||
SkMScalar tol = SK_MScalar1 / (1 << 12)) {
|
||||
return
|
||||
sk_float_almost_equals(m.getFloat(0, 0), 1.0f, tol) &&
|
||||
sk_float_almost_equals(m.getFloat(0, 1), 0.0f, tol) &&
|
||||
sk_float_almost_equals(m.getFloat(0, 2), 0.0f, tol) &&
|
||||
sk_float_almost_equals(m.getFloat(0, 3), 0.0f, tol) &&
|
||||
sk_float_almost_equals(m.getFloat(1, 0), 0.0f, tol) &&
|
||||
sk_float_almost_equals(m.getFloat(1, 1), 1.0f, tol) &&
|
||||
sk_float_almost_equals(m.getFloat(1, 2), 0.0f, tol) &&
|
||||
sk_float_almost_equals(m.getFloat(1, 3), 0.0f, tol) &&
|
||||
sk_float_almost_equals(m.getFloat(2, 0), 0.0f, tol) &&
|
||||
sk_float_almost_equals(m.getFloat(2, 1), 0.0f, tol) &&
|
||||
sk_float_almost_equals(m.getFloat(2, 2), 1.0f, tol) &&
|
||||
sk_float_almost_equals(m.getFloat(2, 3), 0.0f, tol) &&
|
||||
sk_float_almost_equals(m.getFloat(3, 0), 0.0f, tol) &&
|
||||
sk_float_almost_equals(m.getFloat(3, 1), 0.0f, tol) &&
|
||||
sk_float_almost_equals(m.getFloat(3, 2), 0.0f, tol) &&
|
||||
sk_float_almost_equals(m.getFloat(3, 3), 1.0f, tol);
|
||||
}
|
||||
|
||||
GrColorSpaceXform::GrColorSpaceXform(const SkMatrix44& srcToDst)
|
||||
: fSrcToDst(srcToDst) {}
|
||||
|
||||
@ -48,7 +23,6 @@ sk_sp<GrColorSpaceXform> GrColorSpaceXform::Make(SkColorSpace* src, SkColorSpace
|
||||
// Quick equality check - no conversion needed in this case
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
const SkMatrix44* toXYZD50 = as_CSB(src)->toXYZD50();
|
||||
const SkMatrix44* fromXYZD50 = as_CSB(dst)->fromXYZD50();
|
||||
@ -56,13 +30,16 @@ sk_sp<GrColorSpaceXform> GrColorSpaceXform::Make(SkColorSpace* src, SkColorSpace
|
||||
// unsupported colour spaces -- cannot specify gamut as a matrix
|
||||
return nullptr;
|
||||
}
|
||||
SkMatrix44 srcToDst(SkMatrix44::kUninitialized_Constructor);
|
||||
srcToDst.setConcat(*fromXYZD50, *toXYZD50);
|
||||
|
||||
if (matrix_is_almost_identity(srcToDst)) {
|
||||
if (as_CSB(src)->toXYZD50Hash() == as_CSB(dst)->toXYZD50Hash()) {
|
||||
// Identical gamut - no conversion needed in this case
|
||||
SkASSERT(*toXYZD50 == *as_CSB(dst)->toXYZD50() && "Hash collision");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SkMatrix44 srcToDst(SkMatrix44::kUninitialized_Constructor);
|
||||
srcToDst.setConcat(*fromXYZD50, *toXYZD50);
|
||||
|
||||
return sk_make_sp<GrColorSpaceXform>(srcToDst);
|
||||
}
|
||||
|
||||
|
@ -175,6 +175,7 @@ DEF_TEST(ColorSpaceWriteICC, r) {
|
||||
SkASSERT(SkColorSpace_Base::Type::kXYZ == as_CSB(newMonitorSpace)->type());
|
||||
SkColorSpace_XYZ* newMonitorSpaceXYZ = static_cast<SkColorSpace_XYZ*>(newMonitorSpace.get());
|
||||
REPORTER_ASSERT(r, *monitorSpaceXYZ->toXYZD50() == *newMonitorSpaceXYZ->toXYZD50());
|
||||
REPORTER_ASSERT(r, monitorSpaceXYZ->toXYZD50Hash() == newMonitorSpaceXYZ->toXYZD50Hash());
|
||||
REPORTER_ASSERT(r, monitorSpaceXYZ->gammaNamed() == newMonitorSpaceXYZ->gammaNamed());
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user